A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way.
简言:ConstraintLayout是可以灵活设置其内控件位置和大小的ViewGroup。
支持API 9 (Gingerbread)及以上,官方后续仍将对其API和功能进行扩展。
添加
1、 Android Studio版本至少2.3;
2、 在build.gradle中添加依赖,如下:
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.1'
}
约束类型
当前支持(2017.3)
1、 Relative positioning
2、 Margins
3、 Centering positioning
4、 Visibility behavior
5、 Dimension constraints
6、 Chains
7、 Virtual Helpers objects
注意:在约束条件下不能有循环依赖关系。
详看ConstraintLayout.LayoutParams布局属性。
开发者指南
相对位置 Relative positioning
作用:设置控件与另一个控件的相对位置。
可在水平轴与垂直轴约束控件:
- 水平轴:
Left,、Right,、Start、End - 垂直轴:
top、bottom、text baseline

| 序号 | 属性 |
|---|---|
| 1 | layout_constraintLeft_toLeftOf |
| 2 | layout_constraintLeft_toRightOf |
| 3 | layout_constraintRight_toLeftOf |
| 4 | layout_constraintRight_toRightOf |
| 5 | layout_constraintTop_toTopOf |
| 6 | layout_constraintTop_toBottomOf |
| 7 | layout_constraintBottom_toTopOf |
| 8 | layout_constraintBottom_toBottomOf |
| 9 | layout_constraintBaseline_toBaselineOf |
| 10 | layout_constraintStart_toEndOf |
| 11 | layout_constraintStart_toStartOf |
| 12 | layout_constraintEnd_toStartOf |
| 13 | layout_constraintEnd_toEndOf |
以上属性需要另一个控件的id或parent(父容器)作为参考:
<Button
android:id="@+id/buttonB" ...
app:layout_constraintLeft_toLeftOf="parent" />
示例:将按钮B放置到按钮A的右边

<Button android:id="@+id/buttonA" ... />
<Button
android:id="@+id/buttonB" ...
app:layout_constraintLeft_toRightOf="@+id/buttonA" />
边距 Margins
作用:设置target控件与source控件的边距。
示例:将按钮B放置到按钮A右边,并设置边距。B:source控件;A:target控件。

| 序号 | 属性 |
|---|---|
| 1 | android:layout_marginStart |
| 2 | android:layout_marginEnd |
| 3 | android:layout_marginLeft |
| 4 | android:layout_marginTop |
| 5 | android:layout_marginRight |
| 6 | android:layout_marginBottom |
注意:边距只能设置精确的值(包括0)和尺寸引用。
当位置约束target控件View.GONE时,可用以下margin属性指示不同的边距值:
| 序号 | 属性 |
|---|---|
| 1 | layout_goneMarginStart |
| 2 | layout_goneMarginEnd |
| 3 | layout_goneMarginLeft |
| 4 | layout_goneMarginTop |
| 5 | layout_goneMarginRight |
| 6 | layout_goneMarginBottom |
居中设置 Centering positioning
ConstraintLayout的优势是如何处理不可能的约束。
<android.support.constraint.ConstraintLayout ...>
<Button
android:id="@+id/button" ...
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</>
以上示例,除非ConstraintLayout与Button的大小完全相同,否则两个约束不会同时满足。

这种情况下,约束的作用类似于相反的力牵引控件并均分边距。而控件最终会在父容器中处于居中位置。垂直约束雷同。
偏置 Bias
默认情况下,这种对立的约束会促使控件处于居中位置。此时,可以使用Bias属性来调整位置,以达到两侧边距不同的效果。
| 序号 | 属性 |
|---|---|
| 1 | layout_constraintHorizontal_bias |
| 2 | layout_constraintVertical_bias |
示例:设置左侧边距为30%代替默认的50%,如图:

<android.support.constraint.ConstraintLayout ...>
<Button
android:id="@+id/button" ...
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent/>
</>
可见性操作 Visibility behavior
ConstraintLayout有特定的方式处理被设置为View.GONE的控件。
通常,设置GONE的控件不会被显示,也不是布局本身的一部分(虽然标记为GONE,但实际尺寸不会改变)。
但是,就布局计算而言,GONE的控件仍是布局的一部分,区别在于:
- 对于
layout pass,尺寸将被看做是0(基本上被处理成了一个点); - 如果对其他控件有约束,则仍然会被注重,但是所有边距值都将看似为0。

这种特定的行为允许在可以设置控件暂时为GONE的地方构建布局,并且不影响布局,这对制作简单的布局动画也很有用。
注意:上图使用的边距是由
B定义的到A的距离。有些情况下这可能不是想要设置的边距(例:A到父容器一边的边距100dp,B到A边距16dp,此时设置A为GONE,那么B到父容器边距只有16dp)。出于以上原因,当一个作为参考的控件设置为GONE时,可以使用替代的边距值(详看Margins部分)。
尺寸约束 Dimension constraints
ConstraintLayout 最小尺寸
可以自定义ConstraintLayout的最小尺寸。
-
android:minWidth布局的最小宽度 -
android:minHeight布局的最小高度
当ContraintLayout尺寸设置为WRAP_CONTENT时,将使用最小尺寸。
控件尺寸约束
控件尺寸可以通过三种方式设置android:layout_width、android:layout_height属性:
- 使用指定的尺寸(如:123dp、尺寸引用
dimen); - 使用
WRAP_CONTENT,将要求控件自己计算自己的尺寸; - 使用
0dp,相当于MATCH_CONSTRAINT。

前两个类似。最后一个将调整控件,以一致的约束来设置(a:wrap_content;b:0dp)。如果设置了边距,布局计算中将会计算到(c:0dp)。
注意:ContraintLayout中的控件不支持MATCH_PARENT,虽然类似的操作可以使用MATCH_CONSTRAINT与设置相应的left/right 或 top/bottom以parent约束。
比例 Ratio
可以定义一个控件相对于另一个控件的尺寸比例。前提是,需要至少设置一个约束的尺寸为0dp(即MATCH_CONSTRAINT),并通过layout_constraintDimentionRatio属性设置比例。
示例:设置Button的高度与宽度相同
<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1" />
比例值设置方式:
-
float浮点值:表示宽高间的比例 -
width:height方式表示比例
如果宽高都设置为MATCH_CONSTRAINT (0dp),也可以使用比例Ratio。这种情况下,系统会设置最大的那个尺寸来满足所有约束,并保持指定的宽高比。根据一个有尺寸的控件来约束一个指定约束面的控件。可以预先添加W或H来分别约束宽高。例:一个尺寸被两个条件约束(如:宽度0dp并在父容器中居中),那么可以通过在比例Ratio前添加W或H,并用,分隔来标识哪一面应该被约束:
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
高度按照16:9区分,宽度相对父容器按照相同的约束区分。
链 Chains
作用:在单一轴(水平或垂直)上提供群组行为。另一轴可以独立约束。
创建链
Creating a chain
如果一组控件通过双向连接连接在一起,那么这组控件就被认为是一个链。下图显示了一个最小的链。

链头
Chain heads
链由链的第一个元素(链头)上的属性控制:
- 水平链链头:最左侧的控件
- 垂直链链头:最上方的控件

链中的边距
Margins in chains
连接中设置的边距也会计算在内。在链展开的情况下,边距会从分配的空间中扣除。
链样式
Chain Style
当链的第一个元素设置了layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle属性,链样式将按照指定的方式改变(默认是CHAIN_SPREAD)。
-
CHAIN_SPREAD:元素将展开(默认); -
权重链:在
CHAIN_SPREAD模式下,如果一些控件设置了MATCH_CONSTRAINT,这些控件将分担可用空间; -
CHAIN_SPREAD_INSIDE:元素展开,但链的端点不会展开; -
CHAIN_PACKED:链中的元素将包裹在一起。子控件的水平或垂直方向的偏置bias属性会影响包裹中元素的位置。

权重链
Weighted chains
链的作用是在可用空间内均匀的分布元素。如果一个或多个使用MATCH_CONSTRAINT,它们将抢占可用空间(它们之间均分)。属性layout_constraintHorizontal_weight和layout_constraintVertical_weight可以控制使用MATCH_CONSTRAINT的元素如何分配空间。例:一条链控制了两个使用MATCH_CONSTRAINT的元素,第一个元素权重为2,第二个元素权重为1,那么第一个元素占用的空间是第二个元素的两倍。
辅助类 Virtual Helpers objects
除了设置详细的内置属性,也可以在ConstraintLayout中使用特殊的辅助类来帮助布局。目前,Guideline类创建的水平和垂直的参考,允许ConstraintLayout中的控件作为参考相对定位。参考标准将约束控件的布局。
Guideline
public class Guideline extends View
对于ConstraintLayout,Guideline是一个实用的辅助类。辅助类不会在设备上显示(设置为GONE),并且只用于布局意图。只能在ConstraintLayout中使用。
Guideline可以是水平的或垂直的:
- 垂直
Guideline:宽度为0,高度为父容器constraintlayout高度; - 水平
Guideline:高度为0,宽度为父容器constraintlayout宽度。
设置Guideline有三种较为合理的方式:
-
layout_constraintGuide_begin:从布局的左侧或顶部指定距离 -
layout_constraintGuide_end:从布局的右侧或底部指定距离 -
layout_constraintGuide_percent:指定一个布局的宽高比
然后,控件可以以Guideline为参考设置约束,允许多个控件以一个Guideline为参考,或者可以使用百分比设置自适应布局。
在XML中设置Guideline,详看 ConstraintLayout.LayoutParams 的属性,以及 ConstraintSet 中相应的 [setGuidelineBegin(int, int)](https://developer.android.google.cn/reference/android/support/constraint/ConstraintSet.html#setGuidelineBegin(int, int))、[setGuidelineEnd(int, int)](https://developer.android.google.cn/reference/android/support/constraint/ConstraintSet.html#setGuidelineEnd(int, int))、[setGuidelinePercent(int, float)](https://developer.android.google.cn/reference/android/support/constraint/ConstraintSet.html#setGuidelinePercent(int, float)) 方法。
示例:垂直Guideline约束按钮
<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">
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline"
app:layout_constraintGuide_begin="100dp"
android:orientation="vertical"/>
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
app:layout_constraintLeft_toLeftOf="@+id/guideline"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
