ConstraintLayout

introduce

https://developer.android.google.cn/reference/androidx/constraintlayout/widget/ConstraintLayout

https://developer.android.com/develop/ui/views/layout/constraint-layout

https://juejin.cn/post/6949186887609221133#heading-6

Widgets dimension

widget的尺寸可以通过设置android:layout_widthandroid:layout_height的属性值来指定,有如下三种方式:

  • 使用具体值
  • 使用WRAP_CONTENT,这样widget会计算自身的尺寸
  • Using 0dp, which is the equivalent of “MATCH_CONSTRAINT“ (使用0dp,这等于“MATCH_CONSTRAINT” )

img

Group

可以控制一组控件的隐藏和显示

1
2
3
4
5
6
<androidx.constraintlayout.widget.Group
android:id="@+id/gp_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="cl_h4,cl_h2" />
1
((Group)findViewById(R.id.gp_1)).setVisibility(View.GONE);

findViewById(R.id.gp_2).setVisibility(View.INVISIBLE); doesnt not work

https://juejin.cn/post/6844903875569254414#heading-17

Guideline使用

https://developer.android.com/reference/android/support/constraint/Guideline.html

1
2
app:layout_constraintGuide_percent="0.2"
app:layout_constraintGuide_begin="100dp"

特色属性

layout_constraintDimensionRatio

指定高度,宽度随着宽高比自适应

1
2
3
4
5
6
7
<ImageView
android:id="@+id/iv_img01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="@mipmap/img_1"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toLeftOf="parent" />

layout_constraintHorizontal_bias 先设置约束

Bias

上面的水平居中,是使用的与父亲左侧对齐+与父亲右侧对齐. 可以理解为左右的有一种约束力,默认情况下,左右的力度是一样大的,那么view就居中了.

当左侧的力度大一些时,view就会偏向左侧.就像下面这样.

layout_constraintHorizontal_bias 水平约束力
layout_constraintVertical_bias 垂直约束力

1
2
3
4
5
6
7
<android.support.constraint.ConstraintLayout
<Button
android:text="按钮1"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

上面代码就偏左约束

WRAP_CONTENT: 强制约束

我们可能希望使用WRAP_CONTENT,同时仍然强制执行约束以限制最终的尺寸

  • app:layout_constrainedWidth=”true|false”

button1居中显示,button2约束在button1的右边、parent的左边:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aaaaaaa"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="22222222222222222222222222222"
app:layout_constrainedWidth="true"
android:layout_marginTop="40dp"
app:layout_constraintTop_toTopOf="@id/button1"
app:layout_constraintStart_toEndOf="@id/button1"
app:layout_constraintEnd_toEndOf="parent"/>

对button2使不使用app:layout_constrainedWidth="true"的效果如下:

constraintlayout-constrainted-width-before

constraintlayout-constrainted-width-after

约束width前 & 约束width后

占用父布局的比例

chain

3个Button 两两依赖,相当于组成了一个链

Button均分 width = match_constraint (0dp)

图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<Button
android:id="@+id/bt_00"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_00"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_01" />

<Button
android:id="@+id/bt_01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_01"
app:layout_constraintLeft_toRightOf="@+id/bt_00"
app:layout_constraintRight_toLeftOf="@+id/bt_02" />

<Button
android:id="@+id/bt_02"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_02"
app:layout_constraintLeft_toRightOf="@+id/bt_01"
app:layout_constraintRight_toRightOf="parent" />

app:layout_constraintHorizontal_weight=”2”` 

看属性也可以猜到是干嘛用的了.
宽度为wrap_content

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
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
app:layout_constraintTop_toBottomOf="@+id/guideline_00"
android:layout_height="wrap_content">
<Button
android:id="@+id/bt_00"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_00"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_01" />

<Button
android:id="@+id/bt_01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_01"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@+id/bt_00"
app:layout_constraintRight_toLeftOf="@+id/bt_02" />

<Button
android:id="@+id/bt_02"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_weight="1"
android:text="Button_02"
app:layout_constraintLeft_toRightOf="@+id/bt_01"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Button均份 宽度不为match_constraint

宽度为wrap_content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<Button
android:id="@+id/bt_10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button_00"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_11" />

<Button
android:id="@+id/bt_11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button_01"
app:layout_constraintLeft_toRightOf="@+id/bt_10"
app:layout_constraintRight_toLeftOf="@+id/bt_12" />

<Button
android:id="@+id/bt_12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button_02"
app:layout_constraintLeft_toRightOf="@+id/bt_11"
app:layout_constraintRight_toRightOf="parent" />

chainStyle

Chains are controlled by attributes set on the first element of the chain (the “head” of the chain):

img

The head is the left-most widget for horizontal chains, and the top-most widget for vertical chains.第一个元素决定链style

而且只有放在头节点才有效,否则都没用

spread Chain

layout_constraintHorizontal_chainStyle 这个属性默认是spread

元素展开

20220820163354

mineutil

activity_constraint.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<Button
android:id="@+id/bt_00"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_00"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_01" />

<Button
android:id="@+id/bt_01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_01"
app:layout_constraintLeft_toRightOf="@+id/bt_00"
app:layout_constraintRight_toLeftOf="@+id/bt_02" />

<Button
android:id="@+id/bt_02"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button_02"
app:layout_constraintLeft_toRightOf="@+id/bt_01"
app:layout_constraintRight_toRightOf="parent" />
Spread inside chain

endpoints of the chain will not be spread out (两端不会展开)

其实就相当于两端的约束去掉了

20220820182406

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
<Button
android:id="@+id/bt_10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Inside"
android:background="@android:color/holo_blue_light"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_11" />

<Button
android:id="@+id/bt_11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Inside"
android:background="@android:color/holo_blue_light"
app:layout_constraintLeft_toRightOf="@+id/bt_10"
app:layout_constraintRight_toLeftOf="@+id/bt_12" />

<Button
android:id="@+id/bt_12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Inside"
android:background="@android:color/holo_blue_light"
app:layout_constraintLeft_toRightOf="@+id/bt_11"
app:layout_constraintRight_toRightOf="parent" />
Weighted chains

看上面官方的图就能理解了

packed chains
20220820182631
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
<Button
android:id="@+id/bt_20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:text="packed"
app:layout_constraintHorizontal_chainStyle="packed" //第一个有效
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_21" />

<Button
android:id="@+id/bt_21"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:text="packed"
app:layout_constraintLeft_toRightOf="@+id/bt_20"
app:layout_constraintRight_toLeftOf="@+id/bt_22" />

<Button
android:id="@+id/bt_22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:text="packed"
app:layout_constraintLeft_toRightOf="@+id/bt_21"
app:layout_constraintRight_toRightOf="parent" />
Packed Chain with Bias

20220820184349

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
<Button
android:id="@+id/bt_30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:text="packedBias"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_31" />

<Button
android:id="@+id/bt_31"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:text="packedBias"
app:layout_constraintLeft_toRightOf="@+id/bt_30"
app:layout_constraintRight_toLeftOf="@+id/bt_32" />

<Button
android:id="@+id/bt_32"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:text="packedBias"
app:layout_constraintLeft_toRightOf="@+id/bt_31"
app:layout_constraintRight_toRightOf="parent" />

Barrier

用于控制 Barrier 相对于给定的 View 的位置, app:barrierDirection=”right”,表示barrier在constraint_referenced_ids给定ID的右侧,constraint_referenced_ids的id就是左侧的这些控件

输入信息挺有用的

https://mp.weixin.qq.com/s/QIuww9b0TsNjajEUS8c2fg

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen_11">

<TextView
android:id="@+id/tv_order_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="订单编号:10002220000001234"
android:textColor="#ff999999"
android:textSize="19sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />

<TextView
android:id="@+id/tv_order_pro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_11"
android:text="订购产品:爱达康高血压监护服务"
android:textColor="#ff666666"
android:textSize="21sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_order_num" />

<TextView
android:id="@+id/tv_service_team"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="服务团队:爱达康远程监护团队"
android:textColor="#ff666666"
android:textSize="21sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_order_pro" />

<TextView
android:id="@+id/tv_period_valid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="有效期:2019-03-01至2019-12-31"
android:textColor="#ff999999"
android:textSize="19sp"
app:layout_constraintStart_toEndOf="@+id/barrier" />

<TextView
android:id="@+id/tv_order_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_11"
android:text="订购时间:2019-03-11 12:00:00"
android:textColor="#ff666666"
android:textSize="21sp"
app:layout_constraintStart_toEndOf="@+id/barrier"
app:layout_constraintTop_toBottomOf="@+id/tv_period_valid" />

<TextView
android:id="@+id/tv_order_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="订购数量:500次"
android:textColor="#ff666666"
android:textSize="21sp"
app:layout_constraintStart_toEndOf="@+id/barrier"
app:layout_constraintTop_toBottomOf="@+id/tv_order_time" />


<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_order_num,tv_order_pro,tv_service_team" />

</android.support.constraint.ConstraintLayout>

Dimensions constraints

You can define minimum and maximum sizes for the ConstraintLayout itself:

  • android:minWidth set the minimum width for the layout
  • android:minHeight set the minimum height for the layout

可以设置百分比

Practice

需求是美女跟在文字后面,如果文字太长就用省略号

20220821165517

20220821165912

主要着两个属性

1
2
3
app:layout_constrainedWidth="true" // 如果不用这个约束,文字太长,会把直接在Learn more后面
app:layout_constraintHorizontal_bias="0" // 去掉左边的约束
app:layout_constraintHorizontal_chainStyle="packed" // 让文字和美女在一起
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<ImageView
android:id="@+id/iv_duitnow"
android:layout_width="36dp"
android:layout_height="36dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_duit_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="9dp"
android:textColor="#282828"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_duitnow"
app:layout_constraintTop_toTopOf="parent"
android:text="Reload via Transfer:" />

<TextView
android:id="@+id/tv_duitnow_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:lines="1"
android:textColor="#0064FF"
android:textSize="14sp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@+id/img_copy"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="@+id/tv_duit_text"
app:layout_constraintTop_toBottomOf="@+id/tv_duit_text"
android:text="0124455660124455660124455666" />

<ImageView
android:id="@+id/img_copy"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitXY"
android:src="@drawable/meitu111e33"
app:layout_constraintBottom_toBottomOf="@+id/tv_duitnow_id"
app:layout_constraintEnd_toStartOf="@+id/bt_learn_more"
app:layout_constraintStart_toEndOf="@+id/tv_duitnow_id"
app:layout_constraintTop_toTopOf="@+id/tv_duitnow_id" />


<TextView
android:id="@+id/bt_learn_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="7dp"
android:background="@android:color/holo_blue_light"
android:paddingRight="15dp"
android:paddingBottom="7dp"
android:textSize="10sp"
android:textStyle="normal"
app:layout_constraintBottom_toBottomOf="@+id/tv_duitnow_id"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_duitnow_id"
android:text="Learn_More" />

https://blog.yorek.xyz/android/other/constraintlayout/#63-wrap_content-11

https://juejin.cn/post/6844903733948579847

https://jishuin.proginn.com/p/763bfbd5c73f


ConstraintLayout
https://noteforme.github.io/2017/10/15/ConstraintLayout/
Author
Jon
Posted on
October 15, 2017
Licensed under