赞
踩
ConstraintLayout
和 RelativeLayout
相似,其中所有的视图均根据同级视图与父布局之间的关系进行布局,但其灵活性要高于 RelativeLayout
,适合创建复杂的大型布局。
官方教程地址:https://developer.android.google.cn/training/constraint-layout
在项目根目录的 build.gradle
文件中声明:
repositories {
google()
}
将该库作为依赖项添加到项目的 build.gradle
文件中,如以下示例所示
dependencies {
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
// To use constraintlayout in compose
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha07"
}
约束条件如下:
例如下面这个简单的布局,有个按钮位于屏幕左上角
对应的布局代码如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"/>
</androidx.constraintlayout.widget.ConstraintLayout>
其中 parent
代表的是父布局。
注意:在约束性布局中,除非宽高设置成 match_parent
,否则其他场景都需要设置 (上 || 下)&& (左 || 右) 的约束条件, 不然编译器会出现报错警告。
水平居中:
设置 constraintLeft
和 constraintRight
,根据左右两边约束的视图居中。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"/>
</androidx.constraintlayout.widget.ConstraintLayout>
垂直居中:
设置 constraintTop
和 constraintBottom
,根据上下约束的视图居中。
<Button
android:id="@+id/btn"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"/>
居中设置偏移比例
设置 layout_constraintVertical_bias
和 layout_constraintHorizontal_bias
layout_constraintVertical_bias:垂直偏移,范围 0 ~ 1 ,0代表最上方,1代表最下方
layout_constraintHorizontal_bias:水平偏移,范围 0 ~ 1,0代表最左边,1代表最右边
设置 layout_constraintHorizontal_chainStyle
或 layout_constraintVertical_chainStyle
通过链条方式控制一组控件,例如:
1 Spread:视图均匀分布,默认该属性
2 Packed:视图打包一起
3 Spread inside:第一个和最后一个视图固定在链条两端
4 Weighted:权重布局,layout_width = 0dp,layout_constraintHorizontal_weight设置权重
链是一组视图,这些视图通过 双向位置约束条件相互链接到一起,即上图 链中的视图可以垂直或水平分布。
由链条的第一个视图设置 chainStyle
即可。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <Button android:id="@+id/btn1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="btn1"/> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/btn1" app:layout_constraintRight_toLeftOf="@id/btn3" app:layout_constraintTop_toTopOf="@id/btn1" android:text="btn2"/> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/btn2" app:layout_constraintTop_toTopOf="@id/btn1" app:layout_constraintRight_toRightOf="parent" android:text="btn3" /> <Button android:id="@+id/btn4" android:layout_marginTop="64dp" app:layout_constraintTop_toBottomOf="@id/btn1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/btn5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="btn4" app:layout_constraintHorizontal_chainStyle="packed"/> <Button android:id="@+id/btn5" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/btn4" app:layout_constraintRight_toLeftOf="@id/btn6" app:layout_constraintTop_toTopOf="@id/btn4" android:text="btn5"/> <Button android:id="@+id/btn6" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/btn5" app:layout_constraintTop_toTopOf="@id/btn4" app:layout_constraintRight_toRightOf="parent" android:text="btn6"/> <Button android:id="@+id/btn7" android:layout_marginTop="64dp" app:layout_constraintTop_toBottomOf="@id/btn4" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/btn8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="btn7" app:layout_constraintHorizontal_chainStyle="spread_inside"/> <Button android:id="@+id/btn8" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/btn7" app:layout_constraintRight_toLeftOf="@id/btn9" app:layout_constraintTop_toTopOf="@id/btn7" android:text="btn8"/> <Button android:id="@+id/btn9" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/btn8" app:layout_constraintTop_toTopOf="@id/btn7" app:layout_constraintRight_toRightOf="parent" android:text="btn9"/> <Button android:id="@+id/btn10" android:layout_marginTop="64dp" app:layout_constraintTop_toBottomOf="@id/btn7" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/btn11" android:layout_width="0dp" app:layout_constraintHorizontal_weight="1" android:layout_height="wrap_content" android:text="btn10" app:layout_constraintHorizontal_chainStyle="spread_inside"/> <Button android:id="@+id/btn11" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintHorizontal_weight="2" app:layout_constraintLeft_toRightOf="@id/btn10" app:layout_constraintRight_toLeftOf="@id/btn12" app:layout_constraintTop_toTopOf="@id/btn10" android:text="btn11"/> <Button android:id="@+id/btn12" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintHorizontal_weight="2" app:layout_constraintLeft_toRightOf="@id/btn11" app:layout_constraintTop_toTopOf="@id/btn10" app:layout_constraintRight_toRightOf="parent" android:text="btn12"/> </androidx.constraintlayout.widget.ConstraintLayout>
可以添加垂直或水平的引导线来约束视图,并且应用用户看不到该引导线。 可以根据相对于布局边缘的 dp 单位或百分比在布局中定位引导线。
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintGuide_percent="0.5"/>
<Button
android:id="@+id/btn1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="wrap_content"
app:layout_constraintLeft_toRightOf="@id/guideline"
android:layout_height="wrap_content"
android:text="btn1"/>
引导线也是一个控件,只是不会显示出来,orientation
设置垂直或水平方向的引导线,layout_constraintGuide_percent
支持百分比定位引导线,范围 0 ~ 1。
由于 layout_margin
无法设置百分比,我们可以通过 Guideline
替代实现。
上图这种覆盖方式通过布局顺序实现的,btn2
控件布局中在 btn1
控件的下方。
由于 ConstraintLayout
布局中无法设置负数的 margin
,所以如果想覆盖控件的上半部分,可以通过引导线等辅助实现。
<androidx.constraintlayout.widget.Guideline android:orientation="horizontal" app:layout_constraintGuide_percent="0.5" android:id="@+id/space" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:background="@color/colorAccent" android:layout_marginTop="32dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn1" android:text="btn1" app:layout_constraintTop_toBottomOf="@id/space" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn2" android:text="btn2" android:layout_marginStart="64dp" android:background="@color/reset_totp_indicator_color" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/space"/>
layout_constraintHeight_percent
和 layout_constraintWidth_percent
支持通过百分比设置控件的宽高,范围 0 ~ 1 。
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="btn1"
app:layout_constraintHeight_percent="0.3"
app:layout_constraintWidth_percent="0.5"
android:background="@color/reset_totp_indicator_color"/>
layout_width
和 layout_height
必须设置成 0dp
,才可以生效。
当设置 wrap_content
再设置约束条件时会发现约束条件失效了,例如:
<TextView android:text="sdfsfdsdfsdfssdfsdfsdfdsfdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_username" android:textColor="@color/find_pass_text_color" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/btn1" android:maxLines="1" android:ellipsize="end" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_bias="0" /> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:text="btn1" app:layout_constraintHeight_percent="0.3" app:layout_constraintWidth_percent="0.5" android:background="@color/colorAccent"/>
虽然设置了约束条件 app:layout_constraintRight_toLeftOf="@id/btn1"
,但实际并没有生效。
需要设置 layout_constrainedWidth
为true,修改后效果如下:
<TextView android:text="sdfsfdsdfsdfssdfsdfsdfdsfdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_username" android:textColor="@color/find_pass_text_color" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/btn1" android:maxLines="1" android:ellipsize="end" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_bias="0" app:layout_constrainedWidth="true" /> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:text="btn1" app:layout_constraintHeight_percent="0.3" app:layout_constraintWidth_percent="0.5" android:background="@color/colorAccent"/>
有时候适配不同屏幕时,我们不希望尺寸随着屏幕变大而无限拉伸,这时候可以通过 layout_constraintWidth_max
,layout_constraintHeight_max
,layout_constraintWidth_min
,layout_constraintHeight_min
这几个设置宽高的最大或最小值。
需要配合百分比布局 layout_constraintWidth_percent
才可以生效。
<Button
android:id="@+id/btn1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:text="btn1"
android:background="@color/colorAccent"
app:layout_constraintWidth_percent="0.85"
/>
设置宽度最大值为 200dp,修改后显示如下:
<Button
android:id="@+id/btn1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:text="btn1"
android:background="@color/colorAccent"
app:layout_constraintWidth_percent="0.85"
app:layout_constraintWidth_max="200dp"
/>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。