1.介绍
约束布局
ConstraintLayout
本身就是一个ViewGroup,它用来解决布局嵌套过多的问题(嵌套越多,绘制消耗的时间越长),以灵活的方式定位/调整小部件(API 9以上均可使用),相比RelativeLayout更灵活,性能更加的出色,更好的适配屏幕大小不同的机型。Android Studio 2.3开始默认创建Activity是都是使用它。
2.使用
使用它也非常的简单,高版本的AS通常都会自动的添加它的依赖,如果未添加依赖在app/build.gradle中添加相应的依赖即可。
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
2.1 相对定位
即一个组件相对于另一个组件的约束,非常的好理解(与RelativeLayout非常的类似)。
例:要实现B在A的右侧:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1MTMzIjM1UTM1IzMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
按钮A在按钮B的右侧,也可以理解为按钮B的左侧位于按钮A的右侧;其他的方位都一样。我们在代码中的表示如下:
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintLeft_toRightOf="@id/btn1" />
其中最关键的属性为
app:layout_constraintLeft_toRightOf="@id/btn1"
,代表按钮B的左侧位于按钮A的右侧
其中常用的属性还有:
// 值可以为parent,意思就是A的左侧位于父布局的左侧(top_top|bottom_bottom等一样)
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_constraintBaseline_toBaselineOf
,如图所示,两个Button的高度不一致,但是又希望他们文本对齐,这个时候就可以使用
layout_constraintBaseline_toBaselineOf
保证文字相对齐:
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="Button3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="Button4"
app:layout_constraintBaseline_toBaselineOf="@id/btn3"
app:layout_constraintLeft_toRightOf="@id/btn3" />
2.2 角度定位
角度定位指的是利用角度以及距离决定某些控件中心点的坐标。
三个属性为:
-
指定相对于哪个控件app:layout_constraintCircle="@id/btn3"
-
角度app:layout_constraintCircleAngle="160"
-
中心点的距离app:layout_constraintCircleRadius="150dp"
其中的关系如下图所示:
例子:按钮5在按钮3的160度方向距离为150dp
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="Button3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button5"
app:layout_constraintCircle="@id/btn3"
app:layout_constraintCircleAngle="160"
app:layout_constraintCircleRadius="150dp" />
效果图:
2.3 Margin
使用Margin时,用法与其他布局的一致,前提条件是:必须指定了相对应的约束,Margin值只能大于等于0。
唯一特殊的地方:在对应约束的控件隐藏时,相当于一个点,可使用如下Margin来设置隐藏后的Margin值
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
2.4 居中偏移
如何实现居中:即利用相对定位中的4个属性即可
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
偏移(Bias): 使用
app:layout_constraintHorizontal_bias="0.3"
属性即可(值在0-1之间)
1.
layout_constraintHorizontal_bias 水平偏移
2.
layout_constraintVertical_bias 垂直偏移
上下居中,水平偏移为0.3
2.5 尺寸约束
提供了一下四种方式:
- 固定值
-
wrap_content,自己进行计算
当控件的高度或宽度为wrap_content时,可以使用下列属性来控制最大、最小的高度或宽度:
android:minWidth 最小的宽度
android:minHeight 最小的高度
android:maxWidth 最大的宽度
android:maxHeight 最大的高度
- 使用0dp 官方不推荐在ConstraintLayout中使用match_parent,可设置
宽高比:当宽或高至少一个被设置为0dp时,可通过属性layout_constraintDimensionRatio设置宽高比还可以在值的前面加上W或者H0dp(MATCH_CONSTRAINT)配合代替match_parent
app:layout_constraintDimensionRatio="W,2:1" 宽高比2:1
app:layout_constraintDimensionRatio="H,2:1" 高宽比2:1
<Button
android:id="@+id/btn6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button6"
android:layout_marginStart="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn5" />
<!-- 通过layout_constraintDimensionRatio 设置宽高比 -->
<Button
android:id="@+id/btn7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button7"
app:layout_constraintDimensionRatio="W,2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn6" />
效果图:
2.6 链
如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)。
一条链的第一个控件是这条链的链头,我们可以在链头中设置链的Style,相关的Style有:
app:layout_constraintHorizontal_chainStyle="spread|spread_inside|packed"
app:layout_constraintVertical_chainStyle="spread|spread_inside|packed"
- CHAIN_SPREAD : 默认模式(展开元素)
- CHAIN_SPREAD_INSIDE :展开元素,两端靠近parent边缘
- CHAIN_PACKED :控件被整合在一起
- Weighted Chain: 权重链,当宽度或者高度被设置成0dp时,layout_constraintHorizontal_weight 和 layout_constraintVertical_weight控制所占比例
注意:在链中的元素上使用边距时,边距是相加的。A Margin right 10,B Margin left 5,total 15
Style的形式使用下图表示:
使用案例:
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn2" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintLeft_toRightOf="@id/btn1"
app:layout_constraintRight_toLeftOf="@id/btn3" />
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
app:layout_constraintLeft_toRightOf="@id/btn2"
app:layout_constraintRight_toRightOf="parent" />
packed模式:
spread模式:
spread_inside模式:
Weighted Chain模式,必须存在一个0dp:
3.辅助工具的使用
3.1 Optimizer
当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:
- none 无优化
- Standard 仅优化直接约束/屏障约束(默认)
- Direct 优化直接约束
- Barrier 优化屏障约束
- Chain 优化链约束
- Dimensions 优化尺寸测量
3.2 Barrier(屏障)
详参:https://developer.android.google.cn/reference/android/support/constraint/Barrier
A与B的宽度未知,现在让C约束在A或者B的右侧都不对;这种情况可用Barrier解决,它相当于在AB的一侧与C之间加了一个屏障。
使用Barrier后如下图(A B都在屏障内):
主要的属性:
app:barrierDirection="end|top|bottom|start|left|right"
等设置屏障的位置
app:constraint_referenced_ids=””
设置屏障引用的控件,多个值时用’,’隔开
例子:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:text="Button4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="6dp"
android:text="Button5 Button5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button1" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="button1,button2" />
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="10dp"
android:text="为了看到整体的效果,可以切换语言,
此时你会看到Barrier会自动位于较宽的那个textView后面,
也就间接让 textView3 也位于了正确的位置"
app:layout_constraintLeft_toRightOf="@id/barrier"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
效果:
最终在C中引用Barrier的约束即可,使用后不管A或者B的宽度如何变化,C始终都位于屏障的右侧
3.3 Group
详参:https://developer.android.google.cn/reference/android/support/constraint/Group
主要作用:把控件归类为一组,更加便捷的管理显示与否等
控件隐藏前:
使用Group,并且添加相关的依赖:
app:constraint_referenced_ids="btn2,btn3"关联关系
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintLeft_toRightOf="@id/btn1" />
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
app:layout_constraintLeft_toRightOf="@id/btn2" />
<android.support.constraint.Group
app:constraint_referenced_ids="btn2,btn3"
android:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
控件隐藏后:
3.4 Placeholder
详参:https://developer.android.google.cn/reference/android/support/constraint/Placeholder
占位符,可使用setContent设置另一个控件的id,使这个控件移动到占位符的位置.
通过
app:content="@+id/btn1"
属性设置要移动的View
案例:设置Button在右上角,设置Placeholder在左下角,设置content后,Button移动到Placeholder的位置(左下角)
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.constraint.Placeholder
android:id="@+id/ph"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content="@+id/btn1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
</android.support.constraint.ConstraintLayout>
效果:
3.5 Guideline
详参:https://developer.android.google.cn/reference/android/support/constraint/Guideline
布局辅助线,预览的时候帮助我们完成布局(不显示在界面上)
主要属性:
android:orientation="horizontal|vertical"
app:layout_constraintGuide_end = “50dp”
结束位置
app:layout_constraintGuide_begin = “50dp”
开始位置
app:layout_constraintGuide_percent="0.6"
距离顶部的百分比(orientation = horizontal时则为距离左边)
例子:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1" />
<android.support.constraint.Guideline
android:id="@+id/line1"
android:orientation="horizontal"
app:layout_constraintGuide_begin="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.constraint.Guideline
android:id="@+id/line2"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.6"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.constraint.Guideline
android:id="@+id/line3"
android:orientation="horizontal"
app:layout_constraintGuide_end="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
效果:
ConstraintLayout 的使用就简单介绍到这里
参考文章