ConstraintLayout 更灵活的布局

官方定义

A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way


  • 实现两个View之间的圆关系。有3个可以设置的参数:圆心,半径,角度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<TextView
android:id="@+id/tv_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView 0"
android:background="#86b5ce"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView 1"
android:background="#479782"
app:layout_constraintCircle="@id/tv_0"
app:layout_constraintCircleRadius="100dp"
app:layout_constraintCircleAngle="45"
/>

  • 强制布局的约束性
1
2
app:layout_constrainedWidth="true"
app:layout_constrainedHeigth="true"

不强制约束

强制约束

  • Chain
1
2
//在某个头结点设置属性
app:layout_constraintHorizontal_chainStyle="spread"

  • 填充父布局约束
1
2
3
4
5
6
7
//以宽为例,宽设置为0dp,会填充整个父布局可用宽度。
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.5"
//或者
app:layout_constraintWidth_min="100dp"
app:layout_constraintWidth_max="200dp"
  • GoneMargin
1
2
//当控件的左边的约束不可见的时候,可以设置一个Margin来应对。
app:layout_goneMarginLeft="100dp"
  • 设置控件宽高比
1
2
3
4
5
6
7
//宽度和高度中需要有一个设置为0dp,然后设置Ratio,形式为 若高为0dp,则 H,比例:比例
<ImageView
android:layout_width="100dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
app:layout_constraintDimensionRatio="H,16:9" />

  • 设置控件宽高比并且设置宽占父控件的比例。
1
2
3
4
5
6
7
8
9
10
11
//这种情况下默认是居中的。可以通过设置layout_constraintDimensionRatio来居左或者居右
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintDimensionRatio="H,16:9" />


  • Guideline 不占空间,辅助线。可以设置在某个方向上固定高度的位置,或者固定比例的位置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//使用Guideline来实现margin的比例控制
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.2" />
<android.support.constraint.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.2" />
<ImageView
android:layout_width="100dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintLeft_toRightOf="@id/guideline2"
app:layout_constraintTop_toBottomOf="@id/guideline" />

  • Barrier在多个并列的控件边缘设置一个”阻碍“,始终在最边缘的控件边上,以应对并列控件最边缘控件产生变化的情况。
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
<TextView
android:id="@+id/tv_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#86b5ce"
android:text="TextView 0"
android:visibility="visible"
app:layout_goneMarginLeft="100dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#479782"
android:text="TextView 11111111111111111111111"
android:visibility="visible"
app:layout_constraintLeft_toRightOf="@id/barrier"
/>
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
app:layout_constraintTop_toBottomOf="@id/tv_0"
app:layout_constraintDimensionRatio="H,16:9" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="tv_0,imageView" />

  • Group 1.1新增 控制一组控件的可见性。可以让代码更整洁。
1
2
3
4
5
6
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tv_0,imageView"
android:visibility="gone"
/>
  • PlaceHolder 1.1新增 先在布局添加一个PlaceHolder,后续通过setContentId设置View,然后View就会用PlaceHolder的参数来布局了。
1
2
3
4
5
6
<android.support.constraint.Placeholder
android:id="@+id/placeHolder"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="parent"
/>

  • ConstraintSet 是约束规则的合集,可以设置到一个ConstrainLayout上替换其原本的约束。
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
setContentView(R.layout.activity_main);
ConstraintLayout constraintLayout = findViewById(R.id.ct_root);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(this, R.layout.temp);
constraintSet.applyTo(constraintLayout);
//activity_main.xml
<TextView
android:id="@+id/tv_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#86b5ce"
android:text="TextView 0"
android:visibility="visible"
app:layout_goneMarginLeft="100dp" />
//tem.xml
<TextView
android:id="@+id/tv_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView 0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>

左图为老布局,右图为新布局


使用建议

  • 可以用少量层数的LinearLayout和RelativeLayout完成的布局,不使用ConstraintLayout,因为布局嵌套层数少时,使用ConstraintLayout更消耗性能。
  • 当需要实现特殊要求时,比如百分比布局,固定宽高比,控件相同布局不同的页面等,使用ConstrantLayout可以比较方便的实现。

参考