约束布局所具有的优势:
1.较高的性能优势。
布局嵌套层次越高,性能开销越大。而使用ConstraintLayout
,经常就一层嵌套就搞定了,所以其性能要好很多。
2.完美的屏幕适配.
ConstraintLayout
的大小、距离都可以使用比例来设置,所以其适配性更好。
3.书写简单
4.可视化编辑。
ConstraintLayout
也有十分方便完善的可视化编辑器,不用写xml也基本上能实现大部分功能
定位位置
确定位置的属性提供了下面13个属性(就是哪一条边和哪一条边对齐)
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
例如layout_constraintLeft_toRightOf
。constraintLeft
指的当前控件的左边,toRightOf
对应其他控件的右边
View的边界界定图
实现控件居中和偏移量bias
实现居中直接使用如下代码即可
1 2
| app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent"
|
实现控件处于水平方向的1/3的位置。使用偏移量bias属性。bias即偏移量,他们的取值范围从0~1,0即挨着左边,1是挨着右边,所以要使处于1/3处
1 2 3
| app:layout_constraintHorizontal_bias="0.33" 垂直方向 app:layout_constraintVertical_bias="0.33"
|
view控件大小设置
layout_constraintWidth_default属性有三种不同的值:
spread
,默认值,意思是占用所有的符合约束的空间 。直接设置 layout_width = “0dp”
就直接占满整个空间
percent
,意思是按照父布局的百分比设置,需要layout_constraintWidth_percent
设置百分比例
1 2 3 4 5 6 7 8
| <Button android:id="@+id/d" android:layout_width="0dp" android:layout_height="50dp" app:layout_constraintWidth_percent="0.3" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/c" />
|
设置了layout_constraintWidth_percent属性,可以不用指定layout_constraintWidth_default,他会自动设置为percent
wrap
,意思匹配内容大小但不超过约束限制,注意和直接指定宽度为wrap_content的区别就是不超过约束限制
第一行宽度达到约束就不再增加,第二行显示了完整内容
宽高比ratio
layout_constraintDimensionRatio
,即宽和高成一定的比例,其值可以是”width:height”的形式,也可以是width/height的值。该属性生效的前提:宽和高其中有一项为0dp,有constraint。
如果两项都为0dp,则尺寸会设置为满足约束的最大值并保持比例。
链
在一个水平或者竖直方向上,一排view两两互相约束,即为链
链式布局是约束布局常用的另一个强大功能,可以快速实现等分布局等,还可以实现类似LinearLayout布局的weight比重功能。
约束链具有三种模式:
- spread:view之间均匀分布
- spread_inside:除了约束链的头部和尾部贴在两边,其余均匀分布
- packed:所有view紧贴在一起,默认居中
将多个view构建成一个水平方向的链,则需要多个view在水平方向上两两约束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <Button android:id="@+id/k" android:layout_width="0dp" android:layout_height="50dp" android:text="k" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintTop_toBottomOf="@id/j" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/m"/> <Button android:id="@+id/m" android:layout_width="0dp" android:layout_height="50dp" android:text="m" android:layout_marginHorizontal="10dp" app:layout_constraintLeft_toRightOf="@+id/k" app:layout_constraintRight_toLeftOf="@+id/l" app:layout_constraintTop_toBottomOf="@id/j" />
<Button android:id="@+id/l" android:layout_width="0dp" android:layout_height="50dp" android:text="l" app:layout_constraintRight_toRightOf="parent" app:layout_constraintLeft_toRightOf="@id/m" app:layout_constraintTop_toBottomOf="@id/j" />
|
链的第一个view,称为链头。在链头上设置app:layout_constraintHorizontal_chainStyle
或app:layout_constraintVertical_chainStyle
可分别设置水平或垂直链的模式。
使用layout_constraintHorizontal_weight
,来分割剩余空间。
和 android:layout_weight
区别
- layout_weight ,不管当前view的大小设的是多大,都会继续占据剩余空间
- layout_constraintHorizontal_weight,这个只对0dp并且layout_constraintWidth_default为spread的view生效,使其大小按比例分割剩余空间,对于已经设定大小的view不生效
圆形布局
约束布局还提供一种炫酷的圆形布局:可以以角度和距离约束某个view中心相对于另一个view的中心。
app:layout_constraintCircle
: 圆心,值是某个view的id
app:layout_constraintCircleRadius
: 半径
app:layout_constraintCircleAngle
:角度,值是从0-360,0是指整上方
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <Button android:id="@+id/m" android:layout_width="100dp" android:layout_height="50dp" android:text="m" app:layout_constraintLeft_toRightOf="@+id/k" app:layout_constraintRight_toLeftOf="@+id/l" app:layout_constraintTop_toBottomOf="@id/j" />
<!--圆形布局--> <Button android:id="@+id/n" android:layout_width="100dp" android:layout_height="50dp" android:text="圆形布局" app:layout_constraintCircle="@id/m" app:layout_constraintCircleAngle="220" app:layout_constraintCircleRadius="100dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/m"/>
|
辅助组件
约束布局还提供了一系列组件使得可以更灵活地布局。如Group可以同时控制一堆view的可见性,GuideLine可以虚拟一条辅助线等等。
Group:控制可见性
Group是一个虚拟视图,可以通过把viewapp:constraint_referenced_ids
放到里面,统一同时控制这些view的可见性。
1 2 3 4 5
| <androidx.constraintlayout.widget.Group android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/group" app:constraint_referenced_ids="a,b"/>
|
Group也是继承自view的,直接在代码中像普通view一样设置可见性,就能同时控制到img1,img2的可见性了。
Guideline:辅助线
Guideline相当于一条虚拟辅助线,可分为水平、垂直线,帮助定位的。
考虑一个需求,两个view,要在屏幕中间一左一右,若是传统定位,就弄一个线性布局放两个view,然后再把这个线性布局居中。使用约束布局,可以在屏幕正中间放一条虚拟垂直辅助线,然后两个view分别放在这条线左右即可。
android:orientation
设置垂直还是水平
app:layout_constraintGuide_percent
通过百分比设置位置,取值可以是0f-1.0f或0%-100%
app:layout_constraintGuide_begin
设置相对start/top的偏移量,dp
app:layout_constraintGuide_end
设置相对end/bottom的偏移量,dp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.5" />
<Button android:id="@+id/o" android:layout_width="100dp" android:layout_height="50dp" android:text="o" android:layout_marginRight="10dp" app:layout_constraintRight_toLeftOf="@+id/guideline" app:layout_constraintTop_toBottomOf="@id/n" />
<Button android:id="@+id/p" android:layout_width="100dp" android:layout_height="50dp" android:text="p" android:layout_marginLeft="10dp" app:layout_constraintLeft_toRightOf="@id/guideline" app:layout_constraintTop_toBottomOf="@id/n" />
|
Barrier:获取边界范围
Barrier可以获取多个约束view的边界。可以获得所包含的多个view的最左最右等边界。
考虑这样一个需求,左边是text1和text2,另外有一个view,必须放在这两个text的右边
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <TextView android:id="@+id/r" android:layout_width="100dp" android:layout_height="50dp" android:layout_marginLeft="10dp" android:background="@color/black" android:gravity="center" android:text="R" android:textColor="@color/white" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" />
<TextView android:id="@+id/s" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:background="@color/purple_200" android:gravity="center" android:text="ssadadasdasds" android:textColor="@color/white" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/r" />
<Button android:id="@+id/t" android:layout_width="100dp" android:layout_height="50dp" android:layout_marginLeft="10dp" android:text="t" app:layout_constraintBottom_toBottomOf="@+id/s" app:layout_constraintLeft_toRightOf="@+id/r" app:layout_constraintTop_toTopOf="@+id/r" />
|
因为t只能有一个描点,所以以text1为约束点。但text1、text2宽度时动态的,当text2文本过长时,会发生遮挡。
此时barrier就派上用场了,它可以动态获取text1、text2的最右侧,这样只要t依赖改为Barrier的最右侧,就可以解决问题了
app:barrierDirection
,取值有top、bottom、left、right、start、end,用于设置获取的是哪侧,比如上面的例子,获取的是最右侧start/right。
app:constraint_referenced_ids
设置需要包含的view的id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <androidx.constraintlayout.widget.Barrier android:id="@+id/barrier" android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="end" app:constraint_referenced_ids="r,s" />
<TextView android:id="@+id/r" android:layout_width="100dp" android:layout_height="50dp" android:layout_marginLeft="10dp" android:background="@color/black" android:gravity="center" android:text="R" android:textColor="@color/white" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" />
<TextView android:id="@+id/s" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:background="@color/purple_200" android:gravity="center" android:text="ssadadasdasdsasdasda" android:textColor="@color/white" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/r" />
<Button android:id="@+id/t" android:layout_width="100dp" android:layout_height="50dp" android:layout_marginLeft="10dp" android:text="t" app:layout_constraintBottom_toBottomOf="@+id/s" app:layout_constraintLeft_toRightOf="@+id/barrier" app:layout_constraintTop_toTopOf="@+id/r" />
|