约束布局使用详解
一、前言
在一般的安卓开发中,编写界面需要很多嵌套,这会有一定的性能影响,这个时候就可以使用 ConstraintLayout 或 RelativeLayout来减少嵌套,简化布局深度。ConstraintLayot 类似 RelativeLayout,但是更灵活更强大。
-
- 具有更强的性能优势,简化嵌套深度。
-
- 更好的屏幕适配,可以使用比例来适配,效果更好。
-
- 可视化编辑,操作起来不是很完美。
二、使用
- 引入
implementation 'com.android.support.constraint:constraint-layout:1.1.3' - 基本的相对定位
- 下面是一些常用的基本属性,看到名字基本上就知道怎么用了,具体使用看下面示例。
layout_constraintLeft_toLeftOf layout_constraintLeft_toRightOf layout_constraintRight_toLeftOf layout_constraintRight_toRightOf layout_constraintTop_toTopOf layout_constraintTop_toBottomOf layout_constraintBottom_toTopOf layout_constraintBottom_toBottomOf layout_constraintBaseline_toBaselineOf layout_constraintStart_toEndOf layout_constraintStart_toStartOf layout_constraintEnd_toStartOf layout_constraintEnd_toEndOf 
这个图的实现方法如下:主要是子控件和父控件之间的相对定位。
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="在左上角" android:background="@color/red_F7E6ED" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="在右上角" android:background="@color/red_F7E6ED" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="居中显示" android:background="@color/red_F7E6ED" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/>
- 子控件和子控件之间的定位:

<TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="居中显示" android:background="@color/red_F7E6ED" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <TextView android:id="@+id/tv_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="子控件一" android:background="@color/yellow_FF9B52" app:layout_constraintTop_toBottomOf="@+id/tv_center" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <TextView android:id="@+id/tv_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="子控件二" android:background="@color/green_07C0C2" app:layout_constraintTop_toBottomOf="@+id/tv_center" app:layout_constraintEnd_toStartOf="@+id/tv_one"/>
- 子控件之间高度不一样时的定位:

实现居中对齐,顶部和底部对齐,实现如下:
<TextView android:id="@+id/tv_four" android:layout_width="wrap_content" android:layout_height="50dp" android:text="子控件四" android:gravity="center" android:background="@color/red_F7E6ED" android:layout_marginTop="50dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <TextView android:id="@+id/tv_five" android:layout_width="wrap_content" android:layout_height="60dp" android:text="左边顶部对齐" android:gravity="center" android:background="@color/black_" android:layout_marginTop="50dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_four"/> <TextView android:layout_width="wrap_content" android:layout_height="30dp" android:text="底部对齐" android:gravity="center" android:background="@color/green_07C0C2" app:layout_constraintBottom_toBottomOf="@+id/tv_five" app:layout_constraintEnd_toStartOf="@+id/tv_five"/> <TextView android:id="@+id/tv_six" android:layout_width="wrap_content" android:layout_height="30dp" android:text="右边居中对齐" android:gravity="center" android:background="@color/yellow_FF9B52" android:layout_marginTop="50dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_four" app:layout_constraintBaseline_toBaselineOf="@+id/tv_four"/>
居中对齐用到了一个属性:layout_constraintBaseline_toBaselineOf
这个属性是帮助基准线对齐,如果文字不居中无法实现控件整体居中对齐,示例如下:

如果想实现左侧控件和中心控件居中对齐,可以使用如下方法:
- 角度定位,效果如下图,角度和距离都是两个控件的中心作为参考。


<TextView android:id="@+id/tv_nine" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_marginTop="120dp" android:background="@color/red_F7E6ED" android:gravity="center" android:text="子控件九" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:layout_width="wrap_content" android:layout_height="50dp" android:background="@color/green_07C0C2" android:gravity="center" android:text="在子控件九120度方向 180dp 的距离" app:layout_constraintBaseline_toBaselineOf="@+id/tv_nine" app:layout_constraintCircle="@id/tv_nine" app:layout_constraintCircleAngle="110" app:layout_constraintCircleRadius="180dp" app:layout_constraintStart_toStartOf="parent" />
- margin
ConstraintLayout的边距常用属性如下: android:layout_marginStart android:layout_marginEnd android:layout_marginLeft android:layout_marginTop android:layout_marginRight android:layout_marginBottom
和以前的用法基本一样,不过要先约束好子控件的位置才会生效。
- goneMargin
goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值,属性如下: layout_goneMarginStart layout_goneMarginEnd layout_goneMarginLeft layout_goneMarginTop layout_goneMarginRight layout_goneMarginBottom
-
- 尺寸约束
- 使用wrap_content,让控件自己计算大小,用法和以前的用法基本一样,不过可以使用下列属性来控制最大,最小值。
android:minWidth 最小的宽度 android:minHeight 最小的高度 android:maxWidth 最大的宽度 android:maxHeight 最大的高度
- match_parent,不推荐使用,用 0dp 和约束来实现,示例如下:

<TextView android:id="@+id/tv_eleven" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:background="@color/blue_74D3FF" android:gravity="center" android:text="子控件十一" app:layout_constraintTop_toBottomOf="@id/tv_ten2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/>
- 一个控件宽度固定,另一个占据余下空间

<TextView android:id="@+id/tv_twelve" android:layout_width="0dp" android:layout_height="40dp" android:layout_marginTop="20dp" android:background="@color/blue_74D3FF" android:gravity="center" android:text="子控件十二" app:layout_constraintTop_toBottomOf="@id/tv_eleven" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_thirteen"/> <TextView android:id="@+id/tv_thirteen" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:background="@color/green_07C0C2" android:gravity="center" android:text="子控件十三" app:layout_constraintTop_toBottomOf="@id/tv_eleven" app:layout_constraintEnd_toEndOf="parent" />
- 宽高比
<TextView android:id="@+id/tv_fourteen" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintDimensionRatio="1:2" android:layout_marginTop="20dp" android:background="@color/green_07C0C2" android:gravity="center" android:text="子控件十四,宽高比 1:2" app:layout_constraintTop_toBottomOf="@id/tv_twelve" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/tv_fourteen2" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintDimensionRatio="W,1:2" android:layout_marginTop="20dp" android:background="@color/red_FF6D84" android:gravity="center" android:text="子控件十四,宽高比 W,1:2" app:layout_constraintTop_toBottomOf="@id/tv_twelve" app:layout_constraintStart_toEndOf="@+id/tv_fourteen"/> <TextView android:id="@+id/tv_fourteen3" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintDimensionRatio="H,1:2" android:layout_marginTop="20dp" android:background="@color/red_FF6D84" android:gravity="center" android:text="子控件十四,高宽比H, 1:2" app:layout_constraintTop_toBottomOf="@id/tv_twelve" app:layout_constraintStart_toEndOf="@+id/tv_fourteen2"/>
- 实现权重
-
- 三等分

<TextView android:id="@+id/tv_left" android:layout_width="0dp" android:layout_height="30dp" android:text="控件左" app:layout_constraintTop_toBottomOf="@+id/tv_thirteen" android:layout_marginTop="50dp" android:gravity="center" android:background="@color/red_FF8EB7" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_middle"/> <TextView android:id="@+id/tv_right" android:layout_width="0dp" android:layout_height="30dp" android:text="控件右" app:layout_constraintTop_toBottomOf="@+id/tv_thirteen" android:layout_marginTop="50dp" android:gravity="center" android:background="@color/green_07C0C2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_middle"/> <TextView android:id="@+id/tv_middle" android:layout_width="0dp" android:layout_height="30dp" android:text="控件中" app:layout_constraintTop_toBottomOf="@+id/tv_thirteen" android:layout_marginTop="50dp" android:gravity="center" android:background="@color/yellow_FF9B52" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right"/>
-
- 设置比例 2:1:1
-
- 配合layout_constraintHorizontal_chainStyle实现更多效果,如下:

- 3.1 spread + 宽度非0,不设置默认的就是这种效果

<TextView android:id="@+id/tv_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="左侧" android:background="@color/red_FF6D84" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_center"/> <TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="中间" android:background="@color/yellow_FF9B52" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right"/> <TextView android:id="@+id/tv_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="右侧" android:background="@color/green_07C0C2" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_center"/>
- 3.2 spread_inside + 宽度非0,只要在第一个控件设置就可以了。

<TextView android:id="@+id/tv_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="左侧" android:background="@color/red_FF6D84" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_center" app:layout_constraintHorizontal_chainStyle="spread_inside"/> <TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="中间" android:background="@color/yellow_FF9B52" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right"/> <TextView android:id="@+id/tv_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="右侧" android:background="@color/green_07C0C2" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_center"/>
- 3.3 packed + 宽度非 0

<TextView android:id="@+id/tv_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="左侧" android:background="@color/red_FF6D84" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_center" app:layout_constraintHorizontal_chainStyle="packed"/> <TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="中间" android:background="@color/yellow_FF9B52" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right"/> <TextView android:id="@+id/tv_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="右侧" android:background="@color/green_07C0C2" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_center"/>
- 3.4 spread + 宽度为0,spread_inside + 宽度为0,packed + 宽度为0且可以通过weight控制分配比例,显示效果以设置的比例为准

<TextView android:id="@+id/tv_left" android:layout_width="0dp" android:layout_height="30dp" app:layout_constraintHorizontal_weight="1" android:text="控件左" app:layout_constraintTop_toBottomOf="@+id/tv_thirteen" android:layout_marginTop="50dp" android:gravity="center" android:background="@color/red_FF8EB7" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_middle" app:layout_constraintVertical_chainStyle="spread"/> <TextView android:id="@+id/tv_right" android:layout_width="0dp" android:layout_height="30dp" app:layout_constraintHorizontal_weight="1" android:text="控件右" app:layout_constraintTop_toBottomOf="@+id/tv_thirteen" android:layout_marginTop="50dp" android:gravity="center" android:background="@color/green_07C0C2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_middle" app:layout_constraintVertical_chainStyle="spread"/> <TextView android:id="@+id/tv_middle" android:layout_width="0dp" app:layout_constraintHorizontal_weight="1" android:layout_height="30dp" android:text="控件中" app:layout_constraintTop_toBottomOf="@+id/tv_thirteen" android:layout_marginTop="50dp" android:gravity="center" android:background="@color/yellow_FF9B52" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right" app:layout_constraintVertical_chainStyle="spread"/>
-
- 5 layout_constraintHorizontal_bias + packed 实现最后一种效果

如上,3.3中布局总体居中,这时可以通过设置layout_constraintHorizontal_bias 和layout_constraintVertical_bias来控制位置
<TextView android:id="@+id/tv_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="左侧" android:background="@color/red_FF6D84" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_center" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_bias="0.1"/> <TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="中间" android:background="@color/yellow_FF9B52" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right"/> <TextView android:id="@+id/tv_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="右侧" android:background="@color/green_07C0C2" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_center"/>
两个属性一起使用,实现左下角或是右下角有一定间距,通过 margin 也可以实现,
- margin 实现如下:

<TextView android:layout_width="80dp" android:layout_height="80dp" android:text="右下角" android:textColor="@color/white" android:gravity="center" android:background="@color/red" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_margin="10dp"/>
- layout_constraintHorizontal_bias 实现如下:

<TextView android:layout_width="80dp" android:layout_height="80dp" android:text="左下角" android:textColor="@color/white" android:gravity="center" android:background="@color/red" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintHorizontal_bias="0.08" app:layout_constraintVertical_bias="0.98" />
- 4. 其他相关控件
- 4.1 GuideLine
- 距离顶部 100dp 设置一条辅助线:

android:layout_height=”wrap_content”
android:orientation=”horizontal”
app:layout_constraintGuide_begin=“100dp”
/>
- 距顶部 80%的位置设置一条辅助线

android:layout_height=”wrap_content”
android:orientation=”horizontal”
app:layout_constraintGuide_percent=“0.8”
/>
可以自由拖动控制辅助线的位置。
- 4.2 Group 可以方便控制子控件显示或隐藏
<TextView android:id="@+id/tv_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="左侧" android:background="@color/red_FF6D84" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/tv_center" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_bias="0.1"/> <TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="中间" android:background="@color/yellow_FF9B52" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_left" app:layout_constraintEnd_toStartOf="@+id/tv_right"/> <TextView android:id="@+id/tv_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="右侧" android:background="@color/green_07C0C2" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_center"/> <androidx.constraintlayout.widget.Guideline android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.7" /> <androidx.constraintlayout.widget.Group android:layout_width="match_parent" android:layout_height="wrap_content" app:constraint_referenced_ids="tv_left,tv_center" android:visibility="gone"/>
主要是通过 constraint_referenced_ids 这个属性来实现,然后控制 Group 显示或隐藏就能同时控制加入进去的子控件。Group 使用注意事项:
- Group优先于View,下层Group优先于上层。
- Group只可以引用当前ConstraintLayout下的View,子Layout 下的View不可以。
app:constraint_referenced_ids里直接写的是id的字符串,初始化后会通过getIdentifier来反射查找叫该名字的id。所以如果你的项目用了类似AndResGuard的混淆id名字的功能,切记不要混淆app:constraint_referenced_ids里的id,否则在release版本就会因找不到该id而失效。或者也可以通过代码setReferencedIds来设置id。- 4.3 Placeholder
<TextView android:id="@+id/tv_right3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="右侧" android:background="@color/green_07C0C2" android:padding="10dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <androidx.constraintlayout.widget.Placeholder android:layout_width="wrap_content" android:layout_height="wrap_content" app:content="@+id/tv_right3" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/>
- 4.4 Optimizer
当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:
none:无优化
standard:仅优化直接约束和屏障约束(默认)
direct:优化直接约束
barrier:优化屏障约束
chain:优化链约束
dimensions:优化尺寸测量
- 4.5 Barrier

参考
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/223900.html原文链接:https://javaforall.net
