现在大家几乎都使用过ConstraintLayout,但与经常使用的布局相比,可能会面临不熟悉CL的API或者是逐渐增加的新特性,还有可能因为对CL具体行为的理解模糊而导致误用,这篇文章的目的更多的是,全面总结ConstraintLayout的用法和实际行为特性,并不断更新
基于ConstraintLayout 1.1,当前2.0版本处于测试阶段
参考文章:ConstraintLayout入门指南
为什么要引入ConstraintLayout减少布局层级:常用的布局划分成了几个不同的类型,要组合不同的功能需要通过嵌套的形式实现,比如想要按比例布局就要使用layout_weight属性,想要使用layout_weight属性就要使用LinearLayout(以下简称LL)或者TableLayout,然后你在原先同级的每个布局外再嵌套一层布局以使用layout_weight。
更多的布局需求:要实现固定宽高比、百分比布局,灵活控制大小等更高阶的布局需求,原先的各类布局方式都不能很好的支持,可能需要通过Java代码,在运行中二次实现。
想要通过ConstraintLayout来 优化性能,可能并不明显
亦或者你只是想尝试下这款Andorid官方力推的新布局,看看它有什么新特性。
引入lib:1
2
3
4dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
}
开始之前,我们应该意识到在布局文件中Layout主要职责是什么,控制widgets的位置和大小。下面将从这两个方向出发,看看ConstraintLayout是怎么做的。
1. 控制位置
layout中的view都有四个方向left(start), right(end), top, bottom,通过这些方向在两个view之间建立约束来实现基础的位置控制,相对于RelativeLayout,RL中所有的属性CL中都有与之对应的项目,稍加熟悉即可完成转换:
相对于父布局的相对布局属性,CL的规则是:将父布局当做一个id=”parent”的对象来对待:
1.1 Margins
设置普通的margin:
1.2 visibility 对约束的影响
特殊的情况是:连接到visibility为GONE的view时的margin,在ConstraintLayout中,当widgets被设置View.GONE时进行了特殊处理。根据布局的传递,设置为GONE的view相当于大小被设置为0(实际上是被设置成了一个点)
如果他们已经跟其他的组件产生了约束关系,约束关系还是会存在,但是所有的margin都会变成0
也可以使用goneMargin来保持预期的边距
这种特殊的处理,可以在你临时的把view设置为GONE时,不破坏布局结构。
1.3 居中和偏移
居中的设置参考之前于RelativeLayout的对应关系,CL增加了偏移属性,使用偏移可以更好的处理屏幕大小改变时的情景。
布局中设置:1
2
3
4
5
6
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent/>
>
1.4 圆形的位置
使用圆形约束,在创建圆形的菜单时非常有用
1
2
3
4
5
app:layout_constraintCircle="@+id/buttonA"
app:layout_constraintCircleRadius="100dp"
app:layout_constraintCircleAngle="45" />
2. 控制尺寸(大小)
2.1 给ConstraintLayout自己添加大小限制
当ConstraintLayout的大小设置为WRAP_CONTENT时,可以很方便的设置自己的最大宽高
2.2 Widgets的尺寸(大小)约束
和我们在常用的布局中设置宽高一样,控制Widgets的宽度和高度一共有3种方式:固定的大小,如123dp
WRAP_CONTENT 自适应
0dp,等于MATCH_CONSTRAINT,类似于match_parent,会利用所有可用的空间。注意,不建议使用match_parent
2.3 WRAP_CONTENT 强制约束
默认情况下,设置为WRAP_CONTENT的组件不会限制他们的大小,有时会导致超出约束条件的情况,如果需要强制他们满足约束条件的话,使用下面的强制约束1
2app:layout_constrainedWidth="true|false"
app:layout_constrainedHeight="true|false"
2.4 MATCH_CONSTRAINT 大小控制
默认情况下,MATCH_CONSTRAINT 会利用所有可用的空间,通过下面的设置,可以自定义具体的行为layout_constraintWidth_min and layout_constraintHeight_min
layout_constraintWidth_max and layout_constraintHeight_max
layout_constraintWidth_percent and layout_constraintHeight_percent
使用百分比大小时,对应方向的大小必须设置为 MATCH_CONSTRAINT
2.5 使用比例
使用比例有两种情况,而且必须至少有一条边被设置为0dp:如果只有一条边被设置为0dp,设置比例时,将参考另外一条已经确定尺寸的边
如果两条边都被设置为0dp,那么会在满足比例的条件下,设置为最大尺寸
同样的支持直接设置layout_constraintWidth_percent和layout_constraintHeight_percent来使用百分比控制相对于parent的比例1
2
3
4
5
6
7
8
9
10
11
12
13
14
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1.6" />
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1" />
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintTop_toTopOf="parent" />
2.6 Chains
Chains能自定义在同一轴线上view的位置和大小,首先我们来创建一条链,当widgets之间在同一个方向上相互连接(相互约束)时,链就形成了。
2.6.1 链的head
水平方向chain最左边的控件和垂直方向chain最顶部的控件被成为head chain。通过对head chain添加chainStyle属性,可以设置该条chain在水平或垂直方向上的chainStyle
2.6.2 Chain Style1
2layout_constraintHorizontal_chainStyle
layout_constraintVertical_chainStyle
chainStyle属性一共有三种:spread、spread_inside、packed。再配合其他属性,最终可以组成五种chain style:
其他四种chain style的设置和效果都比较简单,重点介绍下Weighted Chain。默认的spread模式,每个元素获得同样的空间,如果一个元素使用了0dp,将会占用剩下的所有可用空间
layout_constraintHorizontal_weight和layout_constraintVertical_weight可以用来控制同样设置为0dp的控件的比例
Weighted Chain中的控件也允许在chain方向上使用wrap_content自适应控件宽/高,且布局时优先满足设置为wrap_content的控件,相当于优先满足设置了指定宽高的控件
当设置了margin时,margin生效的同时weight的比例不变,链上的控件实际占有布局会被压缩
3. 不可见的辅助工具
Guideline
barrier
Group
4. 用代码的方式操作
ps. 选择优化类型
Package Index:
android.support.constraint
android.support.constraint.helper
android.support.constraint.motion
android.support.constraint.utils