ConstraintLayout 详解

概述

ConstraintLayout 是一种构建于弹性 Constraints(约束)系统的新型 Android Layout,使用方法和 RelativeLayout 类似,但是比它更灵活和更容易使用。

依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
To use ConstraintLayout in your project, proceed as follows: 
Ensure you have the latest Constraint Layout library:
1. Click Tools > Android > SDK Manager.
2. Click the SDK Tools tab.
3. Expand Support Repository and then check ConstraintLayout for Android and Solver for ConstraintLayout. Check Show Package Details and take note of the version you're downloading (you'll need this below).
4. Click OK.
5. Add the library as a dependency in your module-level build.gradle file:
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.1'
}
The library version you download may be higher, so be sure the value you specify here matches the version from step 3.
6. In the toolbar or sync notification, click Sync Project with Gradle Files.
Now you're ready to build your layout with ConstraintLayout

现在 Android Studio 2.3 工具默认新建的 layout 就是 ConstraintLayout,作为官方标配。而且支持将其他官方 layout 一键直接转换为 ConstraintLayout

View 的尺寸

三种值

与其他 Layout 不同之处在于,它的 layout_widthlayout_height 不支持设置 match_parent,其属性取值只有以下三种情况:

  • wrap_content
  • 指定具体dp值
  • 0dp(match_constraint,any size)

0dp 的用途

代表填充约束之意(any size),注意不要以为和 match_parent 是一样的;match_parent 是用于填充满当前控件的父布局,而 any size 是用于填充满当前控件的约束规则。

  • 填充屏幕宽度
1
2
3
4
5
6
7
<Spinner
android:id="@+id/spinner_show_checkedtextview"
android:layout_width="0dp"
android:layout_height="wrap_content"
// 左右两边拉伸到和屏幕宽度保持一致
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
  • 设置特定的宽高比
1
2
3
4
5
6
7
8
9
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="126dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="@mipmap/ic_launcher"
// 设置宽和高的比例为2:1
app:layout_constraintDimensionRatio="w,2:1" />

链(chain)

Chain 链是一种特殊的约束,让多个 chain 链连接的 Views 能够平分剩余空间位置。和 LinearLayout 中的权重比 weight 很相似 ,但 Chains 链能做到的远远不止权重比 weight 的功能。

创建链

选择多个想要链接到一起的 Views ,然后再右键选择 Center Horizontally 或者 Center Vertically 来创建水平链或者垂直链。如下,创建一个水平链:

0027_constrainlayout_chain.gif

链的模式

  • spread chain
    Chain 链的默认模式就是 spread 模式,它将平分间隙让多个 Views 布局到剩余空间

0027_constrainlayout_spread_chain.png

  • spread inside chain
    spread inside 模式,它将会把两边最边缘的两个 View 到外向父组件边缘的距离去除,然后让剩余的 Views 在剩余的空间内平分间隙布局

0027_constraintlayout_spread_inside_chain.png

  • packed chains
    packed 模式将所有 Views 打包到一起不分配多余的间隙(当然不包括通过 margin 设置多个 Views 之间的间隙),然后将整个组件组在可用的剩余位置居中。在 packed chain 链模式,打包在一起的 Views 组可以进一步通过控制修改 bias 值来控制打包组的位置,如 bias 模式是 0.5Views 组居中。

0027_constrainlayout_packed_chain.png

链的权重

spreadspread inside 链可以设置每个组件的 weight 权重,类似于 LinearLayoutweight 权重。当前 AS 版本不能直接在视图编辑器设置这个权重,需要在 XML 文件中手动设置。
假设该 View 是在一个水平的 Chain 链中,在 XML 中设置

1
2
android:layout_width="0dp"
app:layout_constraintHorizontal_weight="1"

注意:在 packed 链模式下设置权重 weight 并没有作用。

就是说并不像 spreadspread inside 模式中表现的占据尽可能的剩余空间,在 packed 模式下该组件就会被收缩成 0 大小。

示例

三个 ListView 水平并列排列,使用默认的链模式

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
42
43
44
45
46
47
48
<ListView
// 最左边的ListView
android:id="@+id/lv_array_adapter_left"
// 宽度设置为0dp,同时水平权重设置为1
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_marginTop="16dp"
app:layout_constraintHorizontal_weight="1"
// 最左边
app:layout_constraintLeft_toLeftOf="parent"
// 链组合
app:layout_constraintRight_toLeftOf="@+id/lv_array_adapter_center"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
// 链模式
app:layout_constraintHorizontal_chainStyle="spread" />

<ListView
// 中间的ListView
android:id="@+id/lv_array_adapter_center"
// 宽度设置为0dp,同时水平权重设置为2
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_marginTop="16dp"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintTop_toTopOf="parent"
// 链组合
app:layout_constraintRight_toLeftOf="@+id/lv_array_adapter_right"
app:layout_constraintLeft_toRightOf="@+id/lv_array_adapter_left"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp" />

<ListView
// 最右边的ListView
android:id="@+id/lv_array_adapter_right"
// 宽度设置为0dp,同时水平权重设置为1.5
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_marginTop="16dp"
app:layout_constraintHorizontal_weight="1.5"
app:layout_constraintTop_toTopOf="parent"
// 最右边
app:layout_constraintRight_toRightOf="parent"
// 链组合
app:layout_constraintLeft_toRightOf="@+id/lv_array_adapter_center"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp" />

对应生成的效果图:

0027_constraintlayout_chain_weight.png

参考文档

  1. http://www.jianshu.com/p/a8b49ff64cd3
  2. https://developer.android.com/training/constraint-layout/index.html
  3. https://codelabs.developers.google.com/codelabs/constraint-layout/#0
  4. http://www.tuicool.com/articles/QJBbUfv
  5. 了解使用-constraintlayout-的性能优势
0%