约束布局ConstraintLayout
文章目录
- 一,背景
- 二,控件优点
- 三,项目中引入
- 四,基本使用
- 4.1 相对位置
- 4.2 尺寸约束
- 4.3 宽高比 Ratio
- 4.4 百分比宽高 Percent
- 4.5 偏移量 bias
- 4.6 圆形定位 Circular positioning
- 4.7 权重 weight
- 4.8 辅助线 Guideline
- 4.9 屏障 Barrier
- 4.10 Group
- 4.11 隐藏边距 goneMargin
- 4.12 链 Chains
- 五,ConstraintLayout 2.0 新特性
- 5.1 新增VirtualLayouts:Flow布局
- 5.2 可自定义ConstraintHelper
- 5.3 新增切换状态布局功能:ConstraintLayoutStates
- 5.4 新增创建约束工具类:ConstraintProperties
- PS. 推荐阅读
国际惯例,官网参考文档是最好的学习资料:
使用 ConstraintLayout 构建自适应界面
一,背景
约束布局 ConstraintLayout
,也有人把它称作“增强型的相对布局”,扁平式的布局方式,无任何嵌套,减少布局的层级,优化渲染性能。是最受欢迎的 Jetpack 库之一,其实是 Android Studio 2.2 中主要的新增功能之一,也是 Google 在2016年的 I/O 大会上重点宣传的一个功能。AS 已经将它作为新建页面默认布局了。经历这几年的迭代,功能已经非常的成熟,现在 2.0 正式版本也发布了,也许你已熟悉了旧版本中的功能,并开始用它来快速构建复杂的页面布局,而新版本除了包含旧版本中的所有功能之外,还在 AS 中集成了可以直接预览 XML 的工具,甚至可以直接在预览界面中对布局进行编辑。
二,控件优点
ConstraintLayout
可以理解为 RelativeLayout + LinearLayout 的混合强化版,同时新版 Android Studio 的布局编辑器也提供了对 ConstraintLayout
完善的编辑支持。使用 ConstraintLayout
可以很方便地在一个层级上实现复杂的布局,功能也很完善,是 Android 官方目前非常重视的一个 Layout(替代以前的 RelativeLayout),使用 ConstraintLayout
后基本可以抛弃 LinearLayout 和 RelativeLayout 的使用,完全不需要任何嵌套就可以实现复杂的 UI,使用起来特别清爽。减少了很多的嵌套的层级,这样 View 在渲染的时候,减少了很多多余的 measure
和 layout
的开销,如果嵌套的层次越多,提升的效果越明显。
感兴趣的话看官方给出的性能测试示例:解析ConstraintLayout的性能优势
三,项目中引入
如需在项目中使用ConstraintLayout
,请按以下步骤操作:
- 确保你的
maven.google.com
代码库已在模块级build.gradle
文件中声明:
repositories {google()
}
- 将该库作为依赖项添加到同一个
build.gradle
文件中,如以下示例所示。请注意,最新版本可能与示例中显示的不同:
dependencies {implementation "androidx.constraintlayout:constraintlayout:2.0.4"// To use constraintlayout in composeimplementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha05"
}
- 在工具栏或同步通知中,点击 Sync Project with Gradle Files。
现在,你可以使用 ConstraintLayout
构建布局。
四,基本使用
4.1 相对位置
要在ConstraintLayout
中确定 view 的位置,必须至少添加一个水平和垂直的约束。每一个约束表示到另一个 view、父布局或者不可见的参考线的连接或者对齐。如果水平或者垂直方向上没有约束,那么其位置就是0。
下面是 ConstraintLayout
确定位置的属性,这些属性的值即可以是 parent(父布局),也可以是某个 view 的 id,和同类型的RelativeLayout属性很相似:
ConstraintLayout | RelativeLayout | 作用 |
---|---|---|
layout_constraintLeft_toLeftOf | layout_alignLeft | 与参照控件左对齐 |
layout_constraintLeft_toRightOf | layout_toRightOf | 在参照控件的右边 |
layout_constraintRight_toLeftOf | layout_toLeftOf | 在参照控件的左边 |
layout_constraintRight_toRightOf | layout_alignRight | 与参照控件右对齐 |
layout_constraintTop_toTopOf | layout_alignTop | 与参照控件上对齐 |
layout_constraintTop_toBottomOf | layout_below | 在参照控件底部 |
layout_constraintBottom_toTopOf | layout_alignBottom | 在参照控件的上部 |
layout_constraintBottom_toBottomOf | layout_above | 与参照控件下对齐 |
layout_constraintBaseline_toBaselineOf | layout_alignBaseline | 与参照控件基线对齐 |
layout_constraintStart_toEndOf | ||
layout_constraintStart_toStartOf | ||
layout_constraintEnd_toStartOf | ||
layout_constraintEnd_toEndOf |
说明:这里 start/end 一般情况下和 left/right 是一样的效果,主要是为了做国际化适配,方便从右往左读的语言文字(如阿拉伯文)。
一个简单的页面:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="左对齐"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="右对齐"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="水平居中"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="垂直居中"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="底部对齐"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="水平居中+垂直居中"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
居中显示:
<!--
即view的左边对齐父布局的左边,view的右边对齐父布局的右边,除非这个view的大小刚好充满整个父布局;
否则的话,就是水平居中显示了。我们可以理解为有两个相同的力,把view拉到中间。
-->
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
水平方向的相对位置:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/btn_center"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="水平参照物"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Left_toLeftOf"app:layout_constraintBottom_toTopOf="@id/btn_center"app:layout_constraintLeft_toLeftOf="@id/btn_center"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Right_toLeftOf"app:layout_constraintBottom_toTopOf="@id/btn_center"app:layout_constraintRight_toLeftOf="@id/btn_center"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Right_toRightOf"app:layout_constraintRight_toRightOf="@id/btn_center"app:layout_constraintTop_toBottomOf="@id/btn_center"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Left_toRightOf"app:layout_constraintLeft_toRightOf="@id/btn_center"app:layout_constraintTop_toBottomOf="@id/btn_center"/>
</androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
竖直方向的相对位置:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/btn_center"android:layout_width="wrap_content"android:layout_height="100dp"android:text="竖直参照物"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Top_toTopOf"app:layout_constraintTop_toTopOf="@id/btn_center"app:layout_constraintRight_toLeftOf="@id/btn_center"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Bottom_toTopOf"app:layout_constraintBottom_toTopOf="@id/btn_center"app:layout_constraintRight_toLeftOf="@id/btn_center"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Top_toBottomOf"app:layout_constraintLeft_toRightOf="@id/btn_center"app:layout_constraintTop_toBottomOf="@id/btn_center"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Bottom_toBottomOf"app:layout_constraintLeft_toRightOf="@id/btn_center"app:layout_constraintBottom_toBottomOf="@id/btn_center"/>
</androidx.constraintlayout.widget.ConstraintLayout>
效果如下
4.2 尺寸约束
view 中使用 warp_content 或者固定值等等是没有问题的。但是在 ConstraintLayout
中不推荐使用 match_parent 这个值,如果需要实现跟 match_parent 同样的效果,可以使用 0dp 来代替,其表示 match_parent,即适应约束。其跟 match_parent 还是有区别的,后面的例子(宽高比那一小节)会提到。
我们来看下例子:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/btn_center"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="wrap_content"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:id="@+id/btn_1"android:layout_width="180dp"android:layout_height="wrap_content"android:text="具体数值:180dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/btn_center"/><Buttonandroid:layout_width="0dp"android:layout_height="wrap_content"android:text="0dp(match_parent)"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/btn_1"/></androidx.constraintlayout.widget.ConstraintLayout>
4.3 宽高比 Ratio
在 ConstraintLayout
中,还可以将宽定义成高的一个比例或者高定义成宽的比率。首先,需要将宽或者高设置为0dp(即match_parent),即要适应约束条件。然后通过 layout_constraintDimensionRatio
属性设置一个比率即可。这个比率可以是一个浮点数,表示宽度和高度之间的比率;也可以是“宽度:高度”形式的比率。比如:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="wrap_content"android:layout_height="0dp"android:layout_marginTop="30dp"app:layout_constraintTop_toTopOf="parent"android:text="-------------------宽高比2:1-------------------"app:layout_constraintDimensionRatio="2:1"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>
如果宽和高都设置为0dp(match_parent),那么 layout_constraintDimensionRatio
的值需要先加一个"W,"或者"H,"来表示约束宽度或高度。如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="0dp"android:layout_height="0dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintDimensionRatio="H,16:9"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>
4.4 百分比宽高 Percent
ConstraintLayout
还能使用百分比来设置 view 的宽高。要使用百分比,宽或高同样要设置为 0dp(match_parent)。然后设置以下属性即可:
app:layout_constraintWidth_default="percent" //设置宽为百分比,可以设置percent、spread和wrap
app:layout_constraintWidth_percent="0.3" //0到1之间的值,为占父布局宽度的多少
app:layout_constraintHeight_default="percent" //设置高为百分比,可以设置percent、spread和wrap
app:layout_constraintHeight_percent="0.3" //0到1之间的值,为占父布局宽度的多少
例子如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="0dp"android:layout_height="wrap_content"android:text="宽50%"app:layout_constraintWidth_default="percent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintWidth_percent="0.5"/></androidx.constraintlayout.widget.ConstraintLayout>
注:在早期版本中必需手动指定 app:layout_constraintWidth_default=“percent”
,在之后的版本中如果设置了app:layout_constraintWidth_percent
属性,则可以不用指定。
效果如下:
官网的介绍是这样的:
You can also define one dimension of a widget as a ratio of the other one. In order to do that, you need to have at least one constrained dimension be set to 0dp (i.e., MATCH_CONSTRAINT), and set the attribute layout_constraintDimensionRatio to a given ratio
意思是说约束布局支持子控件设置宽高比,前提条件是至少需要将宽高中的一个设置为0dp。为了约束一个特定的边,基于另一个边的尺寸,可以预先附加W,或H以逗号隔开。
4.5 偏移量 bias
如果想让view的位置偏向某一侧,可以使用以下的两个属性来设置:
layout_constraintHorizontal_bias //水平偏向
layout_constraintVertical_bias //竖直偏向
其值同样也是0到1之间。比如,以下例子为横向偏向左侧30%,默认的居中效果就是50%:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="左边偏向30%"app:layout_constraintHorizontal_bias="0.3"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>
显示效果如下:
4.6 圆形定位 Circular positioning
以一个控件为圆心设置角度和半径定位
- layout_constraintCircle:关联另一个控件,将另一个控件放置在自己圆的半径上,会和下面两个属性一起使用
- layout_constraintCircleRadius:圆的半径
- layout_constraintCircleAngle:圆的角度
4.7 权重 weight
LinearLayout
中可以设置权重,ConstraintLayout
同样也有这个属性。通过设置以下两个属性:
app:layout_constraintHorizontal_weight //水平权重
app:layout_constraintVertical_weight //竖直权重
然后将相连的 view 两两约束好即可。如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/btn_1"android:layout_width="0dp"android:layout_height="wrap_content"android:text="权重为1"app:layout_constraintHorizontal_weight="1"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toLeftOf="@id/btn_2"/><Buttonandroid:id="@+id/btn_2"android:layout_width="0dp"android:layout_height="wrap_content"android:text="权重为2"app:layout_constraintHorizontal_weight="2"app:layout_constraintLeft_toRightOf="@id/btn_1"app:layout_constraintRight_toLeftOf="@id/btn_3"/><Buttonandroid:id="@+id/btn_3"android:layout_width="0dp"android:layout_height="wrap_content"app:layout_constraintHorizontal_weight="2"android:text="权重为2"app:layout_constraintLeft_toRightOf="@id/btn_2"app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
4.8 辅助线 Guideline
Guideline
可以用来辅助布局,通过 Guideline
能创建出一条水平线或者垂直线,该线不会显示到界面上,但是能够利用这些线条来添加约束去完成界面的布局。
Guideline主要的属性有:
android:orientation="horizontal|vertical"
app:layout_constraintGuide_begin="30dp"
app:layout_constraintGuide_end="30dp"
app:layout_constraintGuide_percent="0.5"<!--
android:orientation=”horizontal|vertical”表示是水平或垂直引导线。
app:layout_constraintGuide_begin=”30dp”,如果是水平引导线,则距离布局顶部30dp,如果是垂直引导线,则距离布局左边30dp。
app:layout_constraintGuide_end=”30dp”,如果是水平引导线,则距离布局底部30dp,如果是垂直引导线,则距离布局右边30dp。
app:layout_constraintGuide_percent=”0.5”,如果是水平引导线,则距离布局顶部为整个布局高度的50%,如果是垂直引导线,则距离布局左边文这个布局宽度的50%。
-->
来看个例子:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline_h"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.5"/><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline_v"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.5"/><Buttonapp:layout_constraintLeft_toLeftOf="@id/guideline_v"app:layout_constraintTop_toTopOf="@id/guideline_h"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="辅助线定位"/>
</androidx.constraintlayout.widget.ConstraintLayout>
如下图所示:
4.9 屏障 Barrier
Barrier,直译为障碍、屏障。在约束布局中,可以使用属性constraint_referenced_ids属性来引用多个带约束的组件,从而将它们看作一个整体,Barrier 的介入可以完成很多其他布局不能完成的功能。
开发中有这样的一个需求,看下图:
姓名、联系方式位于左侧区域(随着文本的宽度变化左侧区域的宽度也随之变化),使用传统的布局方式实现嵌套过多,布局不够优雅。那么来看看约束布局是怎么去实现的:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="20dp"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="姓名:"app:layout_constraintBottom_toBottomOf="@+id/et_name"app:layout_constraintTop_toTopOf="@+id/et_name"/><TextViewandroid:id="@+id/tv_contract"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="8dp"android:text="联系方式:"app:layout_constraintBottom_toBottomOf="@+id/et_contract"app:layout_constraintTop_toTopOf="@+id/et_contract"/><EditTextandroid:id="@+id/et_name"android:layout_width="0dp"android:layout_height="wrap_content"android:hint="请输入姓名"app:layout_constraintLeft_toLeftOf="@+id/barrier"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><EditTextandroid:id="@+id/et_contract"android:layout_width="0dp"android:layout_height="wrap_content"android:hint="请输入联系方式"app:layout_constraintLeft_toLeftOf="@+id/barrier"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@+id/et_name"/><androidx.constraintlayout.widget.Barrierandroid:id="@+id/barrier"android:layout_width="wrap_content"android:layout_height="wrap_content"app:barrierDirection="right"app:constraint_referenced_ids="tv_name,tv_contract"/></androidx.constraintlayout.widget.ConstraintLayout>
barrierDirection 指定方向,constraint_referenced_ids引用的控件 id(多个id以逗号隔开)。
4.10 Group
Group用于控制多个控件的可见性。使用非常简单,若 android:visibility="gone"
那么 btn1,btn2 控件都会隐藏。
<androidx.constraintlayout.widget.Groupandroid:layout_width="match_parent"android:layout_height="wrap_content"android:visibility="visible"app:constraint_referenced_ids="btn1,btn2"><Buttonandroid:id="@+id/btn1"android:text="btn1"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/btn2"android:text="btn2"android:layout_width="wrap_content"android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.Group>
4.11 隐藏边距 goneMargin
当约束目标的可见性为View.GONE时,还可以通过以下属性设置不同的边距值:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
4.12 链 Chains
上面这种将相连的 view 两两约束好的实际上就形成了链。在 ConstraintLayout
中可以实现各种不同的链,权重链是其中一种。整个链由链中的第一个view(链头)上设置的属性控制。
官网上一共有4种样式的链:
- Spread:视图是均匀分布的(在考虑外边距之后)。这是默认值。
- Spread inside:第一个和最后一个视图固定在链两端的约束边界上,其余视图均匀分布。
- Weighted:当链设置为 spread 或 spread inside 时,您可以通过将一个或多个视图设置为“match_parent”(0dp) 来填充剩余空间。默认情况下,设置为“match_parent”的每个视图之间的空间均匀分布,但您可以使用 layout_constraintHorizontal_weight 和 layout_constraintVertical_weight 属性为每个视图分配重要性权重。如果您熟悉线性布局中的 layout_weight 的话,就会知道该样式与它的原理是相同的。因此,权重值最高的视图获得的空间最大;相同权重的视图获得同样大小的空间。
- Packed:视图打包在一起(在考虑外边距之后)。 然后,您可以通过更改链的头视图偏差调整整条链的偏差(左/右或上/下)。
layout_constraintHorizontal_chainStyle // 横向约束链
layout_constraintVertical_chainStyle // 纵向约束链
五,ConstraintLayout 2.0 新特性
官方更新文档:What’s New in 2.1
5.1 新增VirtualLayouts:Flow布局
Flow
布局是Chains
的强化版,是一种新的VirtualLayouts
。用于构建流式排版效果:当出现空间不足时,可自动换行或自动延展到屏幕的另一区域。即当需要对多个View进行流式布局 / 不确定其布局空间的实际尺寸时,就可使用Flow布局。
使用步骤:
- 通过属性
constraint_referenced_ids
获取要引用的视图; - 根据这些视图创建一个虚拟的virtual view group;
- 对这些视图进行流式布局。
<androidx.constraintlayout.helper.widget.Flowapp:constraint_referenced_ids="a1,a2,a3"app:flow_wrapMode="aligned"android:layout_width="0dp"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent" />
核心属性:flow_wrapMode
,用于控制元素的排列方式。
属性说明如下:
<androidx.constraintlayout.helper.widget.Flowapp:constraint_referenced_ids="a1,a2,a3"app:flow_wrapMode="aligned"android:layout_width="0dp"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent" />
<!--
NONE : 默认模式。Views不会被包裹到另一行或列。如果它们在屏幕之外,则不能被看到。
CHAIN : CHAIN与Chains非常相似,可以认为是Chains的强化版本。CHAIN是根据orientation逐行或逐列进行排列的,默认的展示风格是SPREAD。
ALIGNED : ALIGNED模式与CHAIN类似,但链式是在将不同行和列的视图对齐后考虑的,默认的样式是SPREAD。
-->
5.2 可自定义ConstraintHelper
ConstraintHelper
是一个用于记录标记 Views 的 Helper,通过引用指定 Views 从而实现具体效果。
使用场景
- 辅助布局:创建一个新的布局方式,避免创建新的 ViewGroup 从而加深层级
- 修改布局:在布局完成后,修改布局效果
- 重新渲染:在View绘制完成后,对View进行修改、重新渲染效果
具体使用:通过继承 ConstraintHelper
类实现 & 重写所需回调,具体如下所示。
// 继承ConstraintHelper类
class carsonhoTest @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {// 复写常用方法override fun updatePostLayout(container: ConstraintLayout?) {super.updatePostLayout(container)getViews(container).forEach { view ->ViewAnimationUtils.createCircularReveal(view, view.width / 3,view.height / 3, 0f,hypot((view.height / 3.0), (view.width / 3.0)).toFloat()).apply {duration = 2000start()}}}
}// 常用方法说明
init() // 初始化调用
updatePreLayout() // 布局前更新
updatePostLayout() // 布局后更新
updatePostMeasure() // 测量后更新
updatePostConstraints() // 更新约束
onDraw() // 进行绘制
5.3 新增切换状态布局功能:ConstraintLayoutStates
ConstraintLayoutStates
用于根据状态切换不同的布局文件。
具体使用
// 步骤1:创建不同状态的layout xml文件,布局文件的root id相同即可。
// 如:states_1、states_2// 步骤2:在xml文件夹下创建管理文件
<?xml version="1.0" encoding="utf-8"?>
<ConstraintLayoutStates xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><Stateandroid:id="@+id/state1"app:constraints="@layout/states_1" /><Stateandroid:id="@+id/state2"app:constraints="@layout/states_2" /></ConstraintLayoutStates>
// 步骤3:使用loadLayoutDescription来加载管理文件
val constraintLayout = findViewById<ConstraintLayout>(R.id.constraint_state)
constraintLayout.loadLayoutDescription(R.xml.constraint_layout_states)
constraintLayout.setOnClickListener {// 点击时切换布局文件constraintLayout.setState(R.id.state2, 0, 0)
}
5.4 新增创建约束工具类:ConstraintProperties
ConstraintProperties
是在代码中创建约束的工具类。
具体使用:在该工具类出来前,修改属性的常用方式是:
ConstraintSet().apply {clone(constraintLayout)setTranslationX(R.id.xxx, 32f)setMargin(R.id.xxx, ConstraintSet.START, 42)applyTo(constraintLayout)
}
对于 ConstraintLayoutStates
,可使用流式 API 修改属性,更加方便快捷。
ConstraintProperties(findViewById(R.id.xxx)).translationZ(8f).margin(ConstraintSet.START, 8).apply()
PS. 推荐阅读
- 使用 ConstraintLayout 构建自适应界面【官方文档】
- 解析ConstraintLayout的性能优势【Google 开发者计划工程师 Takeshi Hagikura】
- Android新特性介绍,ConstraintLayout完全解析【郭霖,拖拽动图讲解】
- ConstraintLayout 完全解析,快来优化你的布局吧【张鸿洋】
- 自律给你自由——设计布局的新姿势【徐宜生】
- ConstraintLayout使用场景必知必会【徐宜生】
- 带你了解Android约束布局ConstraintLayout【四月葡萄】
- ConstraintLayout使用指南
- 妙用ConstraintLayout的Circular positioning【进阶实战,按钮展开效果】
- 实战篇ConstraintLayout的崛起之路
- android ConstraintLayout使用详解
- ConstraintLayout的使用教程
- ConstraintLayout 2.0 新特性详解及实战
- 约束布局ConstraintLayout看这一篇就够了
- ConstraintLayout看完一篇真的就够了么?
- 布局优化:9种让你不得不使用约束布局Constraintlayout的场景
- 万字长文 - 史上最全ConstraintLayout(约束布局)使用详解
- ConstraintLayout使用大全
约束布局ConstraintLayout相关推荐
- 约束布局ConstraintLayout看这一篇就够了
目录 1.介绍 2.为什么要用ConstraintLayout 3.如何使用ConstraintLayout 3.1 添加依赖 3.2 相对定位 3.3 角度定位 3.4 边距 3.5 居中和偏移 3 ...
- Android开发笔记(一百四十九)约束布局ConstraintLayout
约束布局ConstraintLayout是Android Studio 2.2推出的新布局,并从Android Studio 2.3开始成为默认布局文件的根布局,由此可见Android官方对其寄予厚望 ...
- Android :约束布局ConstraintLayout 之 Chains 链式约束
ConstraintLayout Chains 链式约束 1. 链 简介 ( 1 ) Chains ( 链 ) 简介 2. 创建 链 及 分析 生成的代码 ( 1 ) 创建水平链 ( 2 ) 链创建后 ...
- 约束布局ConstraintLayout加快布局速度
Android Studio2.2更新布局设计器,同时,引人了约束布局ConstraintLayout. 简单来说,可以把它看做是相对布局的升级版本,但是区别与相对布局更加强调约束.何为约束,即控件之 ...
- 约束布局ConstraintLayout(官翻篇)
目录 ConstraintLayout Relative positioning 相对定位 Margins 间距 当关联的控件可见性是GONE的时候 Centering positioning and ...
- Android第二讲笔记(约束布局ConstraintLayout)
目录 为什么要使用约束布局ConstraintLayout? 约束布局基本属性 约束布局简单使用方法 示例 示例一(仿QQ消息) 示例二(仿微信登陆界面) 示例三(仿QQ音乐界面) 补充 写在最后 S ...
- 约束布局constraint-layout导入失败的解决方案 - 转
今天有同事用到了约束布局,但是导入我的工程出现错误 **提示错误: Could not find com.Android.support.constraint:constraint-layout: ...
- 约束布局 ConstraintLayout 的使用
目录 前言 1.将ConstraintLayout添加到项目中 2.基本规则 3.示例讲解 3.1居中对齐 3.2 排列 3.3引导线Guideline 3.4计算器示例 3.5宽高比示例 3.6Ch ...
- Android 约束布局:ConstraintLayout GuidLine
默认的约束布局.里面控件是居中的 可以使用参考线Guideline做参考 来画出来心仪的位置 这布局在渲染上面是没有什么东西的 就是运行到手机上Guideline 是啥也没有的 究其原因因为 源码的d ...
最新文章
- 细胞因子风暴与新冠肺炎
- JVM 调优实战--一个案例理解常用工具(命令)
- (旧)子数涵数·Flash——遮罩动画
- asp.net中获得客户端的IP地址
- 浪漫的表白 (5 分)
- struts2 resultType为chain时 传值
- FreeBSD8下安装软件相关
- open_basedir restriction in effect,解决php引入文件权限问题
- 一网打尽!2018网络安全事件最全的盘点
- ARM中C语言和汇编语言互相调用以及实例
- 测试开发工程师的概念怎么来的?
- 信息化管理系统(制造业ERP系统)
- 4十4十4写成乘法算式_乘法算式怎么写
- Linux下软连接的概念
- ADT:Queues
- 二叉查找树与红黑树原理和程序全面介绍
- 国外众测之密码找回漏洞
- 数据分析及可视化——京东上销量最高的鞋子
- 学口腔医学还是学计算机,我国口腔医学的这“四大家族”,最受学霸欢迎,是真正的金饭碗!...
- 数据可视化工具Table-au的破解安装
热门文章
- java eventusermodel_异常读取XLSB文件Apache POI java.io.CharConversionException
- GaussDB高斯数据库(数据库介绍)
- fl水果软件第三方插件FL Studio20.9
- Java实现库存管理系统
- js作用域及作用域链
- IntelliJ IDEA 2020.3.2下载安装教程(公开版)
- mysql配置所有人可连接_mysql配置允许外界连接
- 接入米家(通过米家购买的WIFI模组 串口方式)
- TI CC1310 sub1G的SDK开发之发射功率实测
- SAI+Ps日漫漫画培训视频教程