介绍
约束布局 ConstraintLayout 是一个 ViewGroup,可以在 Api9 以上的 Android 系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件,ConstraintLayout 非常适合使用可视化的方式来编写界面。从 Android Studio 2.3 起,官方的模板默认使用 ConstraintLayout。
ConstraintLayout 官方文档
基本使用
添加依赖
app/build.gradle 文件中添加 ConstraintLayout 的依赖
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
添加约束
新建一个空项目,Android Studio会自动帮我们创建好一个布局,默认使用 ConstraintLayout
我们将 xml 切换到 Design 模式。现在主操作区域内有两个类似于手机屏幕的界面,左边的是预览界面,右边的是蓝图界面。这两部分都可以用于进行布局编辑工作,区别是左边部分主要用于预览最终的界面效果,右边部分主要用于观察界面内各个控件的约束情况。
如果我们想让 Button 位于布局的右下角,可以进行如下操作: 首先从左侧的 Palette 区域拖一个 Button 进去,可以看到 Button 的上下左右各有一个圆圈,这圆圈就是用来添加约束的。每个控件的约束都分为垂直和水平两类,一共可以在四个方向上给控件添加约束。我们给 Button 的右边和下边添加了约束,因此 Button 就会将自己定位到布局的右下角了。
如果想让 Button 居中,就需要给它的上下左右都添加约束: 除此之外,我们还可以使用约束让一个控件相对于另一个控件进行定位。比如说,我们希望再添加一个 Button,让它位于第一个 Button 的正下方,并且间距 84dp: 删除约束
第一种用于删除一个单独的约束,将鼠标悬浮在某个约束的圆圈上,然后该圆圈会变成同心圆,这个时候单击一下,约束线变成实线后,按下键盘上的 Del 键即可删除 第二种用于删除某一个控件的所有约束,选中一个控件,右键 -> Clear Constraints of Selection 第三种用于删除当前界面中的所有约束,点击工具栏中的删除约束图标即可:
Attributes
选中任意一个控件的时候,在右侧的 Attributes 区域就会出现很多的属性选项 在这里可以设置当前控件的所有属性,这里不再进行详细介绍,自己操作一下就知道了。下面介绍 Layout 这一部分内容
我们可以看到有一个纵向的轴和一个横向的轴,这两个轴也是用于确定控件的位置的。我们让第一个 Button 居中显示了,其实就是因为这里纵横轴的值都是50。如果调整了纵横轴的比例,那么Button的位置也会随之改变: 正方形区域,它是用来控制控件大小的。正方形周围输入框能控制边距。中间的符号一共有三种模式可选,每种模式都使用了一种不同的符号表示,点击符号即可进行切换。 表示 wrap_content,此时可以使用下列属性来控制最大、最小的高度或宽度:
android:minWidth 最小的宽度
android:minHeight 最小的高度
android:maxWidth 最大的宽度
android:maxHeight 最大的高度
注意!当 ConstraintLayout 为 1.1 版本以下时,使用这些属性需要加上强制约束,如下所示:
app:constrainedWidth=”true”
app:constrainedHeight=”true”
表示固定大小 表示any size,它有点类似于 match parent,但和 match_parent 并不一样,是属于 ConstraintLayout 中特有的一种大小控制方式,下面我们来重点讲解一下。
首先需要说明,在 ConstraintLayout 中是有 match_parent 的,只不过用的比较少,因为 ConstraintLayout 的一大特点就是为了解决布局嵌套,既然没有了布局嵌套,那么 match_parent 也就没有多大意义了。所以官方不推荐在 ConstraintLayout 中使用 match_parent,可以设置 0dp (MATCH_CONSTRAINT) 配合约束代替 match_parent。
我们将 Button 的宽度指定成any size,它就会自动充满整个布局了: 这和 match_parent 有什么区别呢?其实最大的区别在于,match_parent 是用于填充满当前控件的父布局,而any_size是用于填充满当前控件的约束规则。举个例子更好理解,如果我们有一个新的 Button,它的其中一个约束是添加到当前这个 Button 上的,那么any_size的效果也会发生改变:
我们切换到code 模式看下代码中是如何写的
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button13"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button10" />
</androidx.constraintlayout.widget.ConstraintLayout>
属性
- 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
这些属性根据名字就很容易知道它们的意思。
举例:实现以下效果
<?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="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
android:text="TextView1" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView2"
...
app:layout_constraintLeft_toRightOf="@+id/tv1" />
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView3"
...
app:layout_constraintTop_toBottomOf="@+id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>
layout_constraintLeft_toRightOf
对于一个View的边界界定,官方给了下面这张图: 一般情况下只是用 layout_constraintLeft_toRightOf 效果是这样的: 如图所示,两个 TextView 的高度不一致,但是又希望他们文本对齐,这个时候就可以使用 layout_constraintBaseline_toBaselineOf
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#D8BFD8"
android:gravity="center"
android:text="TextView1" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:background="#DDA0DD"
android:text="TextView2"
app:layout_constraintBaseline_toBaselineOf="@+id/tv1"
app:layout_constraintLeft_toRightOf="@+id/tv1" />
角度定位
角度定位指的是可以用一个角度和一个距离来约束两个空间的中心
上面例子中的 TextView2 使用以下3个属性:
app:layout_constraintCircle="@+id/tv1"
app:layout_constraintCircleAngle="120"(角度)
app:layout_constraintCircleRadius="150dp"(距离)
TextView2 的中心在TextView1的中心的 120度,距离为 150dp
边距 ConstraintLayout 的边距常用属性如下:
- android:layout_marginStart
- android:layout_marginEnd
- android:layout_marginLeft
- android:layout_marginTop
- android:layout_marginRight
- android:layout_marginBottom
看起来跟别的布局没有什么差别,但实际上控件在 ConstraintLayout 里面要实现 margin ,必须先约束该控件在 ConstraintLayout 里的位置,如果不进行约束,margin 是不生效的: 如果在别的布局里,tv1 的位置应该是距离边框的左边和上面有一个 10dp 的边距,但是在 ConstraintLayout 里,是不生效的,因为没有约束 tv1 在布局里的位置。正确的写法如下: goneMargin
goneMargin 主要用于约束的控件可见性被设置为gone 的时候使用的 margin 值,属性如下:
- layout_goneMarginStart
- layout_goneMarginEnd
- layout_goneMarginLeft
- layout_goneMarginTop
- layout_goneMarginRight
- layout_goneMarginBottom
举例:goneMargin 使用 TextView2 的左边约束在 TextView1 的右边,并给 TextView2 设一个app:layout_goneMarginLeft="10dp"
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#D8BFD8"
android:gravity="center"
android:text="TextView1" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#D8BFFF"
android:gravity="center"
android:text="TextView2"
app:layout_constraintLeft_toRightOf="@+id/tv1"
app:layout_goneMarginLeft="10dp" />
效果如图,TextView2 在TextView1 的右边,且没有边距 这个时候把 TextView1 的可见性设为gone ,效果如下:
可以看到 TextView1 消失后,TextView2 有一个距离左边 10dp 的边距。
居中
开始我们通过视图将一个按钮进行了居中显示,我们切换到 code 模式下看 xml 中是如何写的
<Button
android:id="@+id/button10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
同理,水平居中就要在 ConstraintLayout 约束控件的左右为 parent 的左右;垂直居中需在 ConstraintLayout 约束控件的上下为 parent 的上下。
需要 注意 的是 ConstraintLayout 的宽高要设置为match_parent,否则居中不生效
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
......
</androidx.constraintlayout.widget.ConstraintLayout>
偏移
- layout_constraintHorizontal_bias 水平偏移
- layout_constraintVertical_bias 垂直偏移
假如要实现水平偏移,需给 TextView1 的layout_constraintHorizontal_bias 赋一个范围为 0-1 的值。
假如赋值为 0,则 TextView1 在布局的最左侧。假如赋值为 1,则 TextView1 在布局的最右侧。假如假如赋值为 0.5,则水平居中。假如假如赋值为 0.3,则更倾向于左侧。
垂直偏移同理。
假如layout_constraintHorizontal_bias 赋值为 0.3,效果如图:
layout_constraintDimensionRatio 宽高比
当宽或高至少有一个尺寸被设置为 0dp 时,可以通过属性layout_constraintDimensionRatio 设置宽高比
<TextView
android:id="@+id/tv1"
android:layout_width="0dp"
android:layout_height="100dp"
android:background="#D8BFD8"
android:gravity="center"
android:text="TextView1"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
宽设置为 0dp,宽高比设置为 1:1,这个时候 TextView1 是一个正方形: 除此之外,在设置宽高比的值的时候,还可以在前面加W 或H ,分别指定宽度或高度限制:
app:layout_constraintDimensionRatio="H,2:3"指的是 高:宽=2:3
app:layout_constraintDimensionRatio="W,2:3"指的是 宽:高=2:3
链
如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)
举例:实现以下效果
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#DDA0DD"
android:gravity="center"
android:text="TextView1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tv2" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#D8BFD8"
android:gravity="center"
android:text="TextView2"
app:layout_constraintLeft_toRightOf="@+id/tv1"
app:layout_constraintRight_toLeftOf="@+id/tv3" />
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#FFC0CB"
android:gravity="center"
android:text="TextView3"
app:layout_constraintLeft_toRightOf="@+id/tv2"
app:layout_constraintRight_toRightOf="parent" />
一条链的第一个控件是这条链的链头,我们可以在链头中设置 layout_constraintHorizontal_chainStyle 来改变整条链的样式。chains提供了3种样式,分别是:
-
spread —— 展开元素 (默认); 效果如上图 -
spread_inside —— 展开元素,但链的两端贴近 parent; -
packed—— 链的元素将被打包在一起 layout_constraintHorizontal_weight 权重链 可以留意到上面所用到的 3 个 TextView 宽度都为 wrap_content,如果我们把宽度都设为 0dp,这个时候可以在每个 TextView 中设置横向权重。我们使用layout_constraintHorizontal_weight (constraintVertical 为纵向)来创建一个权重链
<TextView
android:id="@+id/tv1"
android:layout_width="0dp"
android:layout_height="40dp"
android:background="#DDA0DD"
android:gravity="center"
android:text="TextView1"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tv2" />
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="40dp"
android:background="#D8BFD8"
android:gravity="center"
android:text="TextView2"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintLeft_toRightOf="@+id/tv1"
app:layout_constraintRight_toLeftOf="@+id/tv3" />
<TextView
android:id="@+id/tv3"
android:layout_width="0dp"
android:layout_height="40dp"
android:background="#FFC0CB"
android:gravity="center"
android:text="TextView3"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintLeft_toRightOf="@+id/tv2"
app:layout_constraintRight_toRightOf="parent" />
辅助工具
除了 ConstraintLayout 自身属性之外,谷歌还提供了很多辅助布局(只是在布局中起辅助作用,并不会在界面真正显示),来使 ConstraintLayout 的功能更加强大。
Guideline
刚才我们已经实现了让一个按钮居中对齐的功能,如果我们想让两个按钮共同居中对齐该怎么实现呢?
其实这个需求很常见,比如说在应用的登录界面,都会有一个登录按钮和一个注册按钮,不管它们是水平居中也好还是垂直居中也好,但肯定都是两个按钮共同居中的。这就需要用到 Guideline。
现在已经向界面中添加了登录和注册这两个按钮,我们希望让这两个按钮在水平方向上居中显示,在垂直方向上都距离底部 152dp,那么就需要先添加一个垂直方向上的 Guideline。
点击通知栏中的 Guidelines 图标可以添加一个垂直或水平方向上的 Guideline,而Guideline 默认是使用的 dp 尺,我们需要选中 Guideline,并点击最上面的箭头图标将它改成百分比尺,拖动到50%的位置。
接着登录按钮的右边向 Guideline 添加约束,登录按钮的下面向底部添加约束,并拖动按钮让它距离底部 152dp。然后给注册按钮的左边向 Guideline 添加约束,注册按钮的下面向登录按钮的下面添加约束。这样就实现了让两个按钮在水平方向上居中显示,在垂直方向上都距离底部 152dp 的功能了。
切换到 code 模式看下 xml 中怎么写的:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns: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">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="152dp"
android:text="登录"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline4" />
<Button
android:id="@+id/button9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册"
app:layout_constraintBottom_toBottomOf="@+id/button"
app:layout_constraintStart_toStartOf="@+id/guideline4" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
Guildline 属性:
- android:orientation 垂直vertical,水平horizontal
- layout_constraintGuide_begin 开始位置
- layout_constraintGuide_end 结束位置
- layout_constraintGuide_percent 距离顶部的百分比(orientation = horizontal时则为距离左边)
自动添加约束
自动添加约束的方式主要有两种,一种叫 Autoconnect,一种叫 Inference,我们先来看第一种。
想要使用 Autoconnect,首先需要在工具栏中将这个功能启用,默认情况是不启用的: Autoconnect 可以根据我们拖放控件的状态自动判断应该如何添加约束,比如我们将 Button 放到界面的正中央,那么它的上下左右都会自动地添加上约束: 不过 Autoconnect 是无法保证百分百准确判断出我们的意图的,如果自动添加的约束并不是你想要的话,还可以在任何时候进行手动修改。总之,可以把它当成一个辅助工具,但不能完全靠它去添加控件的约束。
Inference 也是用于自动添加约束的,但它比 Autoconnect 的功能要更为强大,因为 AutoConnect 只能给当前操作的控件自动添加约束,而 Inference 会给当前界面中的所有元素自动添加约束。因而 Inference 比较适合用来实现复杂度比较高的界面,它可以一键自动生成所有的约束。下面举例说明。
比如界面上现在有两个 TextView,两个 EditText,和两个 Button。 先将各个控件按照界面设计的位置进行摆放,摆放完成之后点击一下工具栏上的 Infer Constraints 按钮,就能为所有控件自动添加约束了: 最总效果:
Group
Group 可以把多个控件归为一组,方便隐藏或显示一组控件
我们用 链 一节的三个 TextView 为例。现在有3个并排的 TextView,用 Group 把 TextView1 和 TextView3 归为一组,再设置这组控件的可见性 xml 中增加
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="tv1,tv3" />
显示结果:
Placeholder
Placeholder 指的是占位符。在 Placeholder 中可使用 setContent() 设置另一个控件的 id,使这个控件移动到占位符的位置
<androidx.constraintlayout.widget.Placeholder
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content="@+id/textview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#cccccc"
android:padding="16dp"
android:text="TextView"
android:textColor="#000000"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
新建一个 Placeholder 约束在屏幕的左上角,新建一个 TextView 约束在屏幕的右上角,在 Placeholder 中设置 app:content="@+id/textview" ,这时 TextView 会跑到屏幕的左上角。
Barrier
屏障,一个虚拟View。主要解决下面遇到的问题: 假设有 3 个控件ABC,AB 的宽是不固定的,C 在 AB 的右边,这个时候 C 无论约束在 A 的右边或者 B 的右边都不对。当出现这种情况可以用 Barrier 来解决。 Barrier 可以在多个控件的一侧建立一个屏障 C 只要约束在 Barrier 的右边就可以了。
<TextView
android:id="@+id/tv1"
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#DDA0DD"
android:gravity="center"
android:text="TextView1" />
<TextView
android:id="@+id/tv2"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#D8BFD8"
android:gravity="center"
android:text="TextView2"
app:layout_constraintTop_toBottomOf="@+id/tv1" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="tv1,tv2" />
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#FFC0CB"
android:gravity="center"
android:text="TextView3"
app:layout_constraintLeft_toRightOf="@+id/barrier" />
app:constraint_referenced_ids 为屏障引用的控件,可设置多个(用, 隔开)
app:barrierDirection 为屏障所在的位置,可设置的值有:bottom、end、left、right、start、top
ConstraintSet 使用,动态修改约束布局
官方文档
以往我们在代码中动态的修改布局中控件的大小、位置以及与其他控件的相对关系时,都需要使用到 LayoutParams ,不同的布局有对应的不同的LayoutParams 的子类,使用起来十分繁琐。而 ConstraintLayout 与之搭配的就是 ConstraintSet
1、创建和初始化ConstraintSet
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(mainLayout)
constraintSet.clone(context, R.layout.my_layout)
constraintSet.clone(otherConstraintSet)
2、设置组件之间的约束
constraintSet.connect(startID: Int, startSide: Int, endID: Int, endSide: Int, margin: Int)
constraintSet.connect(startID: Int, startSide: Int, endID: Int, endSide: Int)
3、可以修改控件尺寸
constrainWidth(int viewId, int width)
constrainHeight(int viewId, int height)
constrainPercentWidth(int viewId, float percent)
constrainPercentHeight(int viewId, float percent)
其他的跟尺寸有关的API还有:
constrainDefaultWidth/constrainDefaultHeight constrainMaxWidth/constrainMaxHeight constrainMinWidth/constrainMinHeight 用来设置一些默认、最大最小尺寸,不常用,可以看以下文章展示的例子 RecyclerView 设置最大高度
4、设置动画
TransitionManager.beginDelayedTransition(mainLayout)
5、apply一下使设置生效
constraintSet.applyTo(rootLayout)
举例:ConstraintSet 练习
xml
<?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:id="@+id/view_constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button2"
app:layout_constraintLeft_toRightOf="@+id/button1"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/operate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Button operate = findViewById(R.id.operate);
ConstraintLayout constraintLayout = findViewById(R.id.view_constraintLayout);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout);
operate.setOnClickListener(v -> {
constraintSet.connect(R.id.button2, ConstraintSet.TOP, R.id.button1, ConstraintSet.BOTTOM, dpToPx(this, 40));
constraintSet.connect(R.id.button2, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT);
constraintSet.constrainWidth(R.id.button2, ConstraintSet.WRAP_CONTENT);
constraintSet.constrainHeight(R.id.button2, dpToPx(this, 100));
TransitionManager.beginDelayedTransition(constraintLayout);
constraintSet.applyTo(constraintLayout);
});
运行结果:
这只是 ConstraintSet的最基本用法,更多用法可以查看文章末尾参考链接
参考 ConstraintLayout 用法全解析 约束布局ConstraintLayout看这一篇就够了 ConstraintLayout 之 ConstraintSet Android新特性介绍,ConstraintLayout完全解析
|