ConstraintLayout简明实用指南
一、为什么要用ConstraintLayout
当布局嵌套深入比较深的时候,往往会伴随着一些性能问题。所以很多时候我们建议使用RelativeLayout或者GridLayout来简化掉布局的深度。而对于简化布局深度,ConstraintLayout几乎可以做到极致。
具体案例
效果图.png需求:需要将底部按钮进行三等分,上部卖价为屏幕居中,买价为占据屏幕3/4的位置
解决:看到这样的布局,大家条件反射应该就是使用RelativeLayout来做并嵌套LinearLayout,底部可以通过weight进行3等分。但是这样就至少需要嵌套一层布局了。如果页面在复杂点嵌套的更多,影响性能。能不能直接一层布局就搞定?能,用ConstraintLayout就行。
二、ConstraintLayout到底是什么
ConstraintLayout,中文称约束布局,在2016年Google I/O大会时提出,2017年2月发布正式版,目前稳定版本为1.0.2。约束布局作为Google今后主推的布局样式,可以完全替代其他布局,降低页面布局层级,提升页面渲染性能。
三、如何使用ConstraintLayout
1.环境搭建
在要使用ConstraintLayout的module的build.gradle文件中引入约束布局库
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.2'
}
2.常用属性介绍
2.1 相对位置属性
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
这些属性,用于设置一个控件相对于其他控件、Guideline或者父容器的位置。以layout_constraintLeft_toLeftOf
为例,其中layout_
部分是固定格式,主要的信息包含在下面两部分:
constraintXXX:指定当前控件需要设置约束的属性部分。如constraintLeft
表示对当前控件的左边进行约束设置。
toXXXOf:其指定的内容是作为当前控件设置约束需要依赖的控件或父容器(可以理解为设置约束的参照物)。并通过XXX指定被依赖对象用于参考的属性。如toLeftOf="parent"
:表示当前控件相对于父容器的左边进行约束设置。
简单的布局效果例子如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_relative_position"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="拉伸全屏"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="居中A"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="在A下方,与A左对齐"
app:layout_constraintLeft_toLeftOf="@id/btn_A"
app:layout_constraintTop_toBottomOf="@id/btn_A" />
</android.support.constraint.ConstraintLayout>
很明显如果要想实现一个横向拉伸全屏的效果只需要设置该控件左右分别对应父控件的左右,并将宽度设为0即可。如果要实现居中并保持原控件大小只需将该控件宽度设置一个值即可(具体数值、wrap_content)
image
我们可以想象成控件是个铁块,设置Left_toLeftOf
与Right_toRightOf
就是在其左右放两块吸铁石,这时候因为两块吸铁石的吸力是相同的,所以就可以把铁块给水平居中了。(宽度为0意味着不控制铁块的大小,自然被吸得变形左右拉伸了)
2.2偏移属性
通过设置偏移属性可以设置让控件更偏向于依赖控件的某一方,偏移设置为0~1之间的值。
layout_constraintHorizontal_bias // 水平偏移
layout_constraintVertical_bias // 垂直偏移
开篇的时候咱们的布局-买价(占据屏幕3/4的位置)就可以使用偏移属性来实现此效果。例子如下:
<TextView
android:id="@+id/tv_buy_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="买价"
app:layout_constraintHorizontal_bias="0.75"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
2.2 链式相连
多个view在同一个方向上双向引用。如下图所示:水平方向A、B、C,A位于B左边,B位于A右边,他们就是一对双向引用。
image
我们开篇的底部3个按钮就可以通过链来进行布局,代码如下:
<TextView
android:id="@+id/tv_buy_up"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:text="模拟买涨"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tv_buy_down"
app:layout_constraintTop_toBottomOf="@id/tv_sell_val" />
<TextView
android:id="@+id/tv_buy_down"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:text="模拟买跌"
app:layout_constraintLeft_toRightOf="@id/tv_buy_up"
app:layout_constraintRight_toLeftOf="@+id/tv_buy_close"
app:layout_constraintTop_toTopOf="@+id/tv_buy_up" />
<TextView
android:id="@+id/tv_buy_close"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:text="模拟平仓"
app:layout_constraintLeft_toRightOf="@id/tv_buy_down"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_buy_down" />
2.3 Guideline
Guideline主要用于辅助布局,即类似为辅助线,横向的、纵向的。该布局是不会显示到界面上的。
所以其有个属性为:android:orientation
取值为vertical
和horizontal
有三种放置Guideline的方式:
- 给定距离左边或顶部一个固定距离(
layout_constraintGuide_begin
) - 给定距离右边或底部一个固定距离(
layout_constraintGuide_end
) - 给定宽高一个百分比距离(
layout_constraintGuide_percent
)
<android.support.constraint.Guideline
android:id="@+id/guideline_r"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="5dp" />
<android.support.constraint.Guideline
android:id="@+id/guideline_l"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="5dp" />
四、总结
对于复杂布局,很多时候不是一种布局就可以解决。这时需要考虑布局嵌套,无形中增加了开发的复杂性和布局的嵌套层级,进而影响了页面性能。随着google推出了ContraintLayout,上述的问题大部分都可以得到有效的解决。(现在新建一个xml都默认使用ContraintLayout布局,可见google推广ContraintLayout的力度)