约束布局ConstraintLayout

ConstraintLayout

好处

用 RelativeLayout 可以解决问题,为什么还要使用 ConstraintLayout 呢?
因为 ConstraintLayout 使用起来比 RelativeLayout 更灵活,性能更出色!
还有一点就是 ConstraintLayout 可以按照比例约束控件位置和尺寸,能够更好地适配屏幕大小不同的机型。可以角度、距离定位

拖动写UI

使用场景

注意的点

  • 找准布局基准元素,一般是界面的固定不变的业务元素,其它组件,根据其约束来进行布局
  • 使用 Group 等虚拟布局组件来简化布局代码
  • 还是有缺点的,因为控件相互依赖很强,牵一发而动全身,后期修改 UI,维护起来很麻烦
    答:多实用辅助线 guideline 把这样相对来说会很好点。
  • 这个布局不存在谁先写;
  • 如何居中: 底部和顶部都和另一个控件平齐就是居中
  • 如果不好写,可以考虑 Guideline、Barrier 等等,在辅助线左右
  • app: layout_constraintHorizontal_weight 类似:LinearLayout 和 weight
  • goneMargin 主要用于约束的控件可见性被设置为 gone 的时候使用的 margin 值
  • layout_constraintHorizontal_bias 水平偏移,假如赋值为0,则 TextView1在布局的最左侧,假如赋值为1,则 TextView1在布局的最右侧,假如假如赋值为0.5,则水平居中
  • 使用 0dp (MATCH_CONSTRAINT)
    官方不推荐在 ConstraintLayout 中使用 match_parent,可以设置 0dp (MATCH_CONSTRAINT) 配合约束代替 match_parent。
    因为 ConstraintLayout 的一大特点就是为了解决布局嵌套,既然没有了布局嵌套,那么 match parent 也就没有多大意义了。
  • 当宽或高至少有一个尺寸被设置为0dp 时,可以通过属性 layout_constraintDimensionRatio 设置宽高比。app: layout_constraintDimensionRatio=”1:1”

辅助工具

Barrier

避免布局嵌套
unknown_filename.3

Guideline

android: orientation 垂直 vertical,水平 horizontal
layout_constraintGuide_begin 开始位置
layout_constraintGuide_end 结束位置
layout_constraintGuide_percent 距离顶部的百分比 (orientation = horizontal 时则为距离左边)。

不会显示再界面上,和 Barrier 区别:Barrier 作用于几个控件,设置屏障。 Guideline 直接就是比例或距离

Group

Group 可以把多个控件归为一组,方便隐藏或显示一组控件
app: constraint_referenced_ids

Placeholder

Placeholder 指的是占位符。在 Placeholder 中可使用 setContent () 设置另一个控件的 id,使这个控件移动到占位符的位置。改变 view 位置。

Flow

Space

android. widget. Space
在 ConstraintLayout 中,虽然不能使用负-margin 的方式来完成传统布局中的一些错位的效果,但是可以借助 Space 来实现类似的功能,例如借助 Space 来实现左边 TextView 在右边 TextView 某一百分比(或者是 dp)对齐的场景。
unknown_filename.6

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:androxmlns: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">

<TextView
android:android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:background="#bebebe"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Space
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/textView2"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintStart_toStartOf="@+id/textView2"
tools:layout_editor_absoluteY="68dp" />

<TextView
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintEnd_toStartOf="@+id/space"
tools:layout_editor_absoluteY="92dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

由于 ConstraintLayout 不支持负-Margin,所以很多场景下,我们都可以借助 Space 等辅助元素来实现中转,完成传统布局下通过-Margin 实现的效果。

#### Layer (Added in 2.0)

Layer 可以看作是它引用的 view 的边界(可以理解为包含这些 view 的一个 ViewGroup,但是 Layer 并不是 ViewGroup,Layer 并不会增加 view 的层级)。另外 Layer 支持对里面的 view 一起做变换。
考虑这么一个场景,*如果一个页面里面有部分 view 需要加个背景,使用 Layer 引用这几个 view,然后给 Layer 设置背景就可以了*。如果不用 Layer,只能另外加个 ViewGroup 包住这几个 View 了,这样会增加 view 的层级,不利于性能。避免布局嵌套,*可以为一组控件统一设置旋转/缩放/位移*

![QQ截图20191026153932](https://obsidian-yupic.oss-cn-beijing.aliyuncs.com/_resources/CoordinatorLayout_&_ConstraintLayout.resources/2023/09/18/09-58-10-f7365e8b25cdf59e435d4f52f1189910-QQ%E6%88%AA%E5%9B%BE20191026153932-81acb8.png)

![unknown_filename](https://obsidian-yupic.oss-cn-beijing.aliyuncs.com/_resources/CoordinatorLayout_&_ConstraintLayout.resources/2023/09/18/09-58-10-8bcf558119843ef1f0bfb0f8afdfd45b-unknown_filename-a03917.png)

### 示例
```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:androxmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.constraintlayout.widget.Group
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="iv_back,tv_title,iv_more" />

<androidx.constraintlayout.widget.Barrier
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="iv_back" />

<android.widget.Space
android:android:layout_width="0dp"
android:layout_height="10dp"
android:layout_marginBottom="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_back" />

<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@android:color/black"
app:layout_constraintBottom_toBottomOf="@+id/space"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:textColor="@android:color/white"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_back" />


<ImageView
android:android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="火影忍者"
android:textSize="30sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/space" />

<ImageView
android:android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_star_title" />

<TextView
android:android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:lines="1"
android:text="名字反反复复反反复复反反复复反反复复反反复复反反复复反反复复反反复复反反复复分"
android:textSize="18sp"
app:layout_constraintLeft_toRightOf="@id/iv_icon"
app:layout_constraintRight_toLeftOf="@+id/iv_right"
app:layout_constraintTop_toTopOf="@+id/iv_icon" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="吧名"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@+id/iv_icon"
app:layout_constraintLeft_toLeftOf="@+id/tv_name" />

<!--这个布局不存在谁先写;如何居中;
如果不好写,可以考虑Guideline、Barrier等等
-->
<ImageView
android:android:layout_width="60dp"
android:layout_height="0dp"
android:layout_marginTop="12dp"
android:layout_marginRight="10dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
app:layout_constraintDimensionRatio="h,4:2"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintLeft_toRightOf="@+id/tv_name"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_name" />

<ImageView
android:android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintTop_toBottomOf="@id/iv_icon" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="内容哈哈哈哈哈哈哈"
android:textColor="@android:color/white"
android:textSize="20sp"
app:layout_constraintTop_toBottomOf="@id/guideline" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="内容哈哈哈哈哈哈哈"
android:textColor="@android:color/white"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/guideline" />

<androidx.constraintlayout.widget.Guideline
android:android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />


</androidx.constraintlayout.widget.ConstraintLayout>

其他

  • 自动添加约束

    unknown_filename.4

  • 在当控件有自己设置的宽度,例如 warp_content、固定值时,我们为控件添加的都是约束“Constraint”,这个约束有点像橡皮筋一样会拉这个控件,但是并不会改变控件的尺寸
    unknown_filename.5

unknown_filename.1
unknown_filename.2


约束布局ConstraintLayout
http://peiniwan.github.io/2024/04/ee7163cfe8cf.html
作者
六月的雨
发布于
2024年4月6日
许可协议