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>