ConstraintLayout最详细使用,减少嵌套优化ui,提升app性能
作者:岩浆李的游鱼leo2
来源:https://juejin.cn/post/7071165641973530638#heading-5
可能你觉得ConstraintLayout属性多,且属性长而弃用它,那你错失了这个大宝贝。
因为在复杂布局,我们会一直用RelativeLayout和LinearLayout去嵌套,因为嵌套的ViewGroup会导致手机多次测量和绘制,从而影响性能,如果嵌套严重可能出现掉帧或卡顿。
使用ConstraintLayout一招入魂。一句话概括是:传统布局能实现的,它能轻松实现实现。传统布局不能实现的,它也能实现。
一、为什么要用呢?
这里举个2个简单的例子。
1.1、例1
如图下图所示,我们分别用RelativeLayout和ConstraintLayout去实现它:
1.1.1、使用RelativeLayout实现如下
1<RelativeLayout...>
2 <TextView
3 android:id="@+id/txt_a"
4 android:layout_centerHorizontal="true"
5 .../>
6
7 <RelativeLayout
8 android:layout_alignTop="@+id/txt_a"
9 android:layout_toLeftOf="@+id/txt_a"
10 android:layout_alignBottom="@+id/txt_a"
11 ...>
12
13 <TextView
14 android:layout_centerInParent="true"
15 android:id="@+id/txt_b"
16 .../>
17 </RelativeLayout>
18
19</RelativeLayout>
这里使用了伪代码,把无关紧要的属性去掉了。相信懂的人都明白。这里用图层表示下,如下:
最外层是 RelativeLayout(根布局)
红色TextView_A 在顶部且横向居中。
使用绿色 RelativeLayout上边和下边和A齐平,从而保证绿色RelativeLayout高度和A一样。且宽度满屏,在A左边
蓝色TextView_B 在绿色RelativeLayout里居中。
那么接下来看看ConstraintLayout如何实现?
1.1.2、使用ConstraintLayout实现如下
1<androidx.constraintlayout.widget.ConstraintLayout...>
2
3 <TextView
4 android:id="@+id/txt_a"
5 app:layout_constraintRight_toRightOf="parent"
6 app:layout_constraintLeft_toLeftOf="parent"
7 .../>
8
9 <TextView
10 app:layout_constraintRight_toLeftOf="@+id/txt_a"
11 app:layout_constraintLeft_toLeftOf="parent"
12 app:layout_constraintTop_toTopOf="@+id/txt_a"
13 app:layout_constraintBottom_toBottomOf="@+id/txt_a"
14 android:id="@+id/txt_b"
15 .../>
16
17</androidx.constraintlayout.widget.ConstraintLayout>
我们继续看下,他的图层关系,真的简洁。
1.2、例2
如图下图所示,我们分别用RelativeLayout和ConstraintLayout去实现它:
在xml里。我们无法用RelativeLayout去实现,如下分析
B在A下方,通过 android:layout_below="@+id/txt_a"实现
B要在A底部边框上,垂直居中。那么我们要知道B的height。B再使用marginTop="-height/2"才能达到效果。所以在xml里无法实现,只能去代码里动态计算。
使用ConstraintLayout则可轻松完成:
1<androidx.constraintlayout.widget.ConstraintLayout ...>
2
3 <TextView
4 android:id="@+id/txt_a"
5 app:layout_constraintRight_toRightOf="parent"
6 app:layout_constraintLeft_toLeftOf="parent"
7 .../>
8
9 <TextView
10 app:layout_constraintRight_toRightOf="@+id/txt_a"
11 app:layout_constraintLeft_toLeftOf="@+id/txt_a"
12 app:layout_constraintTop_toBottomOf="@+id/txt_a"
13 app:layout_constraintBottom_toBottomOf="@+id/txt_a"
14 android:id="@+id/txt_b"
15 .../>
16
17</androidx.constraintlayout.widget.ConstraintLayout>
上面只是简单的2个小例子,实战上在复杂布局里,真的有太多好处。接下我们具体说说把。
二、ConstraintLayout各属性介绍
2.1、相对定位
2.1.1、例1,如图:靠右边
实现如图功能:
1<TextView
2 ...
3 app:layout_constraintRight_toRightOf="parent"
4 />
layout_constraintRight_toRightOf
属性还有left、right、top、bottom、start、end等搭配使用。什么意思呢?
第一个Right代表 本控件的右边
第二个Right代表 要位于目标控件右边。
所以app:layout_constraintRight_toRightOf="parent";红色A的右边位于父容器的右边
注意start、end是因为很多国家阅读习惯不一样,比如我们是习惯从左往右阅读。所以start对于我们来说就是left,end就是right。
2.1.2、例2,如图:居中
实现如图功能:
1<TextView
2 ...
3 app:layout_constraintRight_toRightOf="parent"
4 app:layout_constraintLeft_toLeftOf="parent"
5 />
右边和父控件右边对齐,左边和父控件左边对齐。这样就可以达到横向居中,同理竖直。
注意这里居中了。同样还可以用margin进行偏移。也可以利用属性app:layout_constraintHorizontal_bias="0.5",进行横向偏移,0.5意思也还算居中。同理竖直的属性。
2.1.3、例3,如图:充满屏幕
比如B要在A的右边,且相对A上下居中,而且B要充满剩余横屏:
1<TextView
2 app:layout_constraintLeft_toRightOf="@+id/txt_a"
3 app:layout_constraintRight_toRightOf="parent"
4 app:layout_constraintTop_toTopOf="@+id/txt_a"
5 app:layout_constraintBottom_toBottomOf="@id/txt_a"
6 android:layout_width="0dp"
7 ...
8 />
要想充满全屏把宽度设置为0dp。然后通过以下代码:
app:layout_constraintLeft_toRightOf="@+id/txt_a";B的左边和A的右边对齐
app:layout_constraintRight_toRightOf="parent";B的右边和父容器的右边对齐
这样B就在A的右边,且横向充满屏。注意:在约束布局里match_parent是不生效的。
要想B竖直方向与A平行的话,通过如下代码:
app:layout_constraintTop_toTopOf="@+id/txt_a";B的上边和A的上边对齐
app:layout_constraintBottom_toBottomOf="@id/txt_a";B的下边和A的下边对齐
这样就可以让B在A右边,上下居中。
2.1.4、例4,如图:不嵌套居中
在列表里我们经常会遇到这样的需求,A是一张图片,title是标题,des是描述。用RelativeLayout的做法是:继续用一个layout布局包裹title和des,居中然后放在A的右边。
用ConstraintLayout的话不用嵌套,3个view就搞定了。如下:
1<ImageView
2 ...
3 />
4
5<TextView
6 app:layout_constraintTop_toTopOf="@+id/image"
7 app:layout_constraintBottom_toTopOf="@+id/txt_des"
8 android:id="@+id/txt_title"
9 ...
10 />
11
12<TextView
13 app:layout_constraintTop_toBottomOf="@+id/txt_title"
14 app:layout_constraintBottom_toBottomOf="@+id/image"
15
16 * 这个时候你会发现还没有居中因为还缺了一条约束,title在des上边;
17 android:id="@+id/txt_des"
18 ...
19 />
因为例3,已经讲过如何全屏了,这里主要讲title和des如何居中:
des 在title下面;app:layout_constraintTop_toBottomOf="@+id/txt_title"
title上边和图片A上边对齐;app:layout_constraintTop_toTopOf="@+id/image"
des下边和图片A下边对齐;app:layout_constraintBottom_toBottomOf="@+id/image"
这个时候你会发现还没有居中因为还缺了一条约束,title在des上边;app:layout_constraintBottom_toTopOf="@+id/txt_des",这和RelativeLayout有些区别
- *
这里还有一个属性文本基线对齐,和RelativeLayout里的 layout_alignBaseline 是一样的效果
app:layout_constraintBaseline_toBaselineOf="@+id/txt_a"
关于相对定位已经讲完了。
2.2、角度定位
如图:
实现代码如下:
1<TextView
2 android:id="@+id/txt_a"
3 ...
4 />
5
6<TextView
7 app:layout_constraintCircle="@+id/txt_a";
8 app:layout_constraintCircleAngle="90"
9 app:layout_constraintCircleRadius="100dp"
10 android:id="@+id/txt_b"
11 ...
12 />
app:layout_constraintCircle="@+id/txt_a";B相对于A角度定位
app:layout_constraintCircleAngle="90";角度定位角度为90°
app:layout_constraintCircleRadius="100dp";B中心与A中心相差100dp
这个时候我也在想有什么用呢?我觉得可以用在某些自定义view上。比如圆形menu、实现时钟更简单了。我用属性动画,实现一个效果你就明白了。录制有点卡顿,真机不会..
2.3、边距
2.3.1、margin
margin 值要生效,一定是伴随约束属性的。什么意思呢,要实现如图功能:
代码实现如下:
1<TextView
2 android:id="@+id/txt_a"
3 ...
4 />
5
6<TextView
7 android:layout_marginLeft="20dp"
8 app:layout_constraintLeft_toRightOf="@+id/txt_a"
9 android:id="@+id/txt_b"
10 ...
11 />
比如B左边和A的右边对齐app:layout_constraintLeft_toRightOf="@+id/txt_a",此时在B上加上margin值生效
如果这个时候在A上加上android:layout_marginRight="50dp",是不生效的。谨记
- *
2.3.2、goneMargin
goneMargin 属性比较有意思。比如要实现如下功能,从图1-->图2:
图1如下:
图2如下:
隐藏A的时候B要置顶排布。在RelativeLayout里,我们只需要在A里使用Margin_Bottom="20dp",然后对A进行隐藏就可以实现了。但是在ConstraintLayout里,因为margin生效必须要有约束,所以这个时候B就要使用goneMargin属性,实现代码如下:
1<TextView
2 android:id="@+id/txt_a"
3 android:visibility="gone"
4 ...
5 />
6
7//意思就是当有约束的控件隐藏时,goneMargin就会生效,那么B就会置顶排布。
8<TextView
9 android:id="@+id/txt_b"
10 app:layout_constraintTop_toBottomOf="@+id/txt_a"
11 android:layout_marginTop="20dp"
12 app:layout_goneMarginTop="0dp"
13 ...
14 />
2.4、尺寸
在ConstraintLayout里,设置尺寸大小的有3个:
设置固定的dp值
wrap_content
0dp(MATCH_CONSTRAINT),前面讲过match_parent是不生效的。如果想达到match_parent的效果只能通过0dp和约束来达到。
2.4.1、满屏
比如控件A满屏(在2.1.3一样),如下效果:
则通过如下代码实现:
1<TextView
2 android:layout_width="0dp"
3 app:layout_constraintLeft_toLeftOf="parent"
4 app:layout_constraintRight_toRightOf="parent"
5 ...
6 />
2.4.2、layout_constraintWidth_max
属性 layout_constraintWidth_max 在使用dp固定值的时候和 android:maxWidth="100dp"
用法是一致的。
但是layout_constraintWidth_max可以搭配属性
app:layout_constraintWidth_percent="0.5" 使用,什么意思呢。
比如我们要实现红色区域占父容器宽度的一半:
实现代码如下:
1<TextView
2 app:layout_constraintLeft_toLeftOf="parent"
3 android:layout_width="0dp"
4 android:text=""
5 app:layout_constraintWidth_max="wrap"
6 app:layout_constraintWidth_percent="0.5"
7 ...
8 />
这里这样设置的时候,意思最大宽度是父容器的一半。注意这里text=""空的时候,会像图中直接展示父容器的一半,假设我们给text="A"设置上值后,如下图,那么只会展示A的宽度,但最大宽度是父容器一半。
2.4.3、app:layout_constrainedWidth
app:layout_constrainedWidth="true"
属性,是按约束去限制宽度,什么意思呢?我们先不加上这条属性,实现如下图效果是这样的:
代码是这样的:
1<TextView
2 android:id="@+id/txt_a"
3 ...
4 />
5
6<TextView
7 app:layout_constraintLeft_toLeftOf="@id/txt_a"
8 app:layout_constraintRight_toRightOf="@id/txt_a"
9 app:layout_constraintTop_toBottomOf="@+id/txt_a"
10 android:id="@+id/txt_b"
11 android:layout_width="wrap_content"
12 android:text="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
13 ...
14 />
给txt_b加上 app:layout_constrainedWidth="true" 属性后,就会实现下面的效果:
意思就是B的最大宽度按照A的宽度来约束,这里要注意的是,B的宽度是wrap_content。假设这里是0dp的话,那这里就另外一种情况了,意思就是B的宽度和A的宽度一样宽。
2.4.4、layout_constraintDimensionRatio 宽高比
app:layout_constraintDimensionRatio="1:1" ,宽高比,注意这一条属性要生效的话要达到2个条件:
其中一条边为0dp
其中一条边为固定值或wrap_content
比如要实现如下,一个正方形的A:
代码如下:
1<TextView
2 android:id="@+id/txt_a"
3 android:layout_width="0dp"
4 android:layout_height="50dp"
5 app:layout_constraintDimensionRatio="1:1"
6 ...
7 />
2.5、链/约束.
指多个控件在一条方向上相互约束,形成一条链子似的。(这里还不算是线性布局, 因为还没加权重) 比如实现如下:
代码如下:
1<TextView
2 android:id="@+id/txt_1"
3 app:layout_constraintLeft_toLeftOf="parent"
4 app:layout_constraintRight_toLeftOf="@+id/txt_2"
5 ...
6 />
7
8<TextView
9 android:id="@+id/txt_2"
10 app:layout_constraintLeft_toRightOf="@+id/txt_1"
11 app:layout_constraintRight_toLeftOf="@id/txt_3"
12 ...
13 />
14
15<TextView
16 android:id="@+id/txt_3"
17 app:layout_constraintLeft_toRightOf="@id/txt_2"
18 app:layout_constraintRight_toRightOf="parent"
19 ...
20 />
这样就在横向方向形成一条链子了(同理纵向),在一条链子的第一个控件也就是链头,我们可以加上layout_constraintHorizontal_chainStyle来改变整条链的样式,有3中
spread就是上面的样子
spread_inside
packed
上面的降的宽度都是wrap_content,如果我们把宽度设置为0do然后通过属性
layout_constraintHorizontal_weight (同理纵向),加上权重后,就是我们的线性布局。比如实现如下:
代码:
1<TextView
2 android:id="@+id/txt_1"
3 android:layout_width="0dp"
4 app:layout_constraintHorizontal_weight="2"
5 app:layout_constraintLeft_toLeftOf="parent"
6 app:layout_constraintRight_toLeftOf="@+id/txt_2"
7 ...
8 />
9
10<TextView
11 android:id="@+id/txt_2"
12 android:layout_width="0dp"
13 app:layout_constraintHorizontal_weight="1"
14 app:layout_constraintLeft_toRightOf="@+id/txt_1"
15 app:layout_constraintRight_toLeftOf="@id/txt_3"
16 ...
17 />
18
19<TextView
20 android:id="@+id/txt_3"
21 android:layout_width="0dp"
22 app:layout_constraintHorizontal_weight="1"
23 app:layout_constraintLeft_toRightOf="@id/txt_2"
24 app:layout_constraintRight_toRightOf="parent"
25 ...
26 />
2.6、辅助工具
2.6.1、Guideline
guideline和辅助先一样,运行项目的时候,不会显示在界面上。也不用担心会消耗性能,因为在其onDraw方法里,没有具体的实现。guideline属性具体如下:
android:orientation="vertical" 纵向辅助线,同理横向
然后就是确定辅助线的位置,通过下面3个属性,多个出现时只会有一个生效,权重是百分比 > begin > end
app:layout_constraintGuide_percent="0.5" 在父布局的百分比位置
app:layout_constraintGuide_begin="10dp" 距离父布局开始位置,横向为左,纵向为顶部
app:layout_constraintGuide_end="10dp" 距离父布局末尾位置
比如我们之前经常会写 时间轴 类似的控件。就可以用这个guideline辅助完成。
2.6.2、Barrier
假设有3个控件A、B、C,如果我们A,B的宽度不固定,同时又希望C在A,B的右边。如果用一个布局把A,B包裹起来,然后让C在A,B右边可以实现,如果不像嵌套就要通过Barrier了,如下图:
实现代码如下:
1<TextView
2 android:id="@+id/txt_1"
3 ...
4 />
5
6<TextView
7 android:id="@+id/txt_2"
8 app:layout_constraintTop_toBottomOf="@+id/txt_1"
9 ...
10 />
11
12<androidx.constraintlayout.widget.Barrier
13 android:id="@+id/barrier"
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content"
16 app:barrierDirection="right"
17 app:constraint_referenced_ids="txt_1,txt_2" />
18
19<TextView
20 android:id="@+id/txt_3"
21 app:layout_constraintLeft_toRightOf="@+id/barrier"
22 ...
23 />
Barrier属性有:
app:barrierDirection="right" 为屏障时,哪个方向的屏障,图中是A和B的右边
app:constraint_referenced_ids="txt_1,txt_2" 为屏障引用的id,用逗号隔开
注意,这里是为减少布局嵌套。必要时我觉得可以灵活运用嵌套。
2.6.3、Group
被布局Layout嵌套的控件A,B,我们要隐藏他只需要隐藏这个嵌套布局Layout即可。在ConstraintLayout里,没有了布局嵌套隐藏A,B就通过Group实现:
1<androidx.constraintlayout.widget.Group
2 android:visibility="gone"
3 android:id="@+id/group"
4 android:layout_width="wrap_content"
5 android:layout_height="wrap_content"
6 app:constraint_referenced_ids="txt_1,txt_2"
7 />
2.6.4、Placeholder:小重点。
网上很多资料对这Placeholder都一比带过。看了我这里的介绍,你会更清楚怎么使用Placeholder。
Placeholder从名字看,就是占位的意思。你可以在一个页面设置多个不同位置的占位。然后通过代码setContentId直接可以改变某个view移动到我们的占位图里。什么意思呢。请看下图:
我在界面上设置了2个Placeholder。通过2个按钮,控制蓝色TextView处于在哪个PlaceHolder里。
首先通过app:content="@+id/txt_blue",让蓝色textView默认在placeholder_1的位置。
注意蓝色textView还是需要在xml里的。
2个按钮我没写上去懂的都懂,那2个按钮上的代码呢?注意看了。这可能是google还没有解决这话bug。下面我来说下
当点击按钮“在位置2里”,把蓝色textView放进placeholde_2,通过placeholde_2.setContentId(R.id.txt_2);
注意此时placeholde_1还是占据着蓝色textView的高度。
当点击“在位置1里”,我们首先要把placeholde_2里蓝色TextView的引用清空掉,用placeholde_2.setContentId(-1);
因为placeholde_1有之前蓝色TextView的引用,虽然是同一个东西,但是设置会不生效。必须清楚掉之前的引用(看源码得出来的结果)。通过placeholde_1.setContentId(-1);
最后通过placeholde_1.setContentId(R.id.txt_2);就可以使蓝色textView又回到了placeholde_1身上了
具体代码如下:
1findViewById(R.id.buttonPanel).setOnClickListener(v ->{
2 placeholde_2.setContentId(R.id.txt_2);
3});
4
5findViewById(R.id.buttonPane2).setOnClickListener(v ->{
6 placeholde_2.setContentId(-1);
7 placeholde_1.setContentId(-1);
8 placeholde_1.setContentId(R.id.txt_2);
9});
如果这个时候,我们想只要Placeholder移除了蓝色TextView。我们就让Placeholder也隐藏不可见。其实是有办法的。
步骤1:给Placeholder加上属性app:placeholder_emptyVisibility="gone"。
步骤2:除了以上步骤,我们还要搭配setContentId(-1),才可以实现效果。
看效果:
代码实现如下:
1findViewById(R.id.buttonPanel).setOnClickListener(v ->{
2 placeholde_1.setContentId(-1);
3 placeholde_2.setContentId(R.id.txt_2);
4});
5
6findViewById(R.id.buttonPane2).setOnClickListener(v ->{
7 placeholde_2.setContentId(-1);
8 placeholde_1.setContentId(R.id.txt_2);
9});
2.6.5、Layer
Layer什么效果呢。比如A B C在如图排布,想在想要有一个黑色背景包裹A,B,C,达到如图效果:
实现如下:
1<androidx.constraintlayout.helper.widget.Layer
2 android:id="@+id/layer"
3 android:background="#000"
4 app:constraint_referenced_ids="txt_a,txt_b,txt_c"
5 android:padding="15dp"
6 ...
7 />
8
9<TextView
10 android:id="@+id/txt_a"
11 ...
12 />
13
14
15<TextView
16 android:id="@+id/txt_b"
17 ...
18 />
19
20
21<TextView
22 android:id="@+id/txt_c"
23 ...
24 />
经过我实际测试,其实Layer能完全代替的了2.6.3的Group,但是不能实现Barrier的功能。
2.6.6、Flow
直接看图把,简单实现这种网格布局:
代码如下:
1<androidx.constraintlayout.helper.widget.Flow
2 android:layout_width="0dp"
3 android:layout_height="wrap_content"
4 app:layout_constraintLeft_toLeftOf="parent"
5 app:layout_constraintRight_toRightOf="parent"
6 app:layout_constraintTop_toTopOf="parent"
7 app:flow_verticalGap="10dp"
8 app:flow_wrapMode="aligned"
9 app:flow_maxElementsWrap="4"
10 app:constraint_referenced_ids="txt_1,txt_2,txt_3,txt_4,txt_5,txt_6" />
11<TextView
12 android:id="@+id/txt_1"
13 ...
14 />
15
16<TextView
17 android:id="@+id/txt_2"
18 ...
19 />
20
21<TextView
22 android:id="@+id/txt_3"
23 ...
24 />
25
26<TextView
27 android:id="@+id/txt_4"
28 ...
29 />
30
31<TextView
32 android:id="@+id/txt_5"
33 ...
34 />
35
36<TextView
37 android:id="@+id/txt_6"
38 ...
39 />
1<TextView
2 android:id="@+id/txt_7"
3 android:layout_width="0dp"
4 android:layout_height="0dp"
5 android:text="7"
6 app:layout_constraintLeft_toLeftOf="@+id/txt_3"
7 app:layout_constraintRight_toRightOf="@+id/txt_4"
8 app:layout_constraintBottom_toBottomOf="@+id/txt_6"
9 app:layout_constraintTop_toTopOf="@+id/txt_6"
10 ...
11 />
没有约束就可以实现这种效果了。而且因为不是嵌套txt_7可以根据Flow里的元素进行约束实现自己想要的样式,这里就不过多介绍了,感兴趣的朋友可以自己去试试,介绍下属性把:
app:flow_wrapMode="aligned" 有3个值。
| aligned | none | chain | chain2 |
|---|---|---|---|
| 绝对对齐(也就是网格对齐的方式) | 默认方式,会排成一排,屏幕宽度不够放时,2边出去 | ||
| 和绝对对齐有点出入的是,比如6个元素,第一排4个,第二排是2个,这2个元素会平分横屏宽度 | 和none类似,区别是,不够放时,会换行其他 |
app:flow_maxElementsWrap="4" 一行几个元素
app:flow_verticalGap="10dp" 竖直间距
app:flow_horizontalGap="10dp" 横向间距
android:orientation="horizontal" 水平方向的流式还是竖直方向的流式
app:flow_verticalAlign ="top" 值有top,bottom,center,baseline。每一行元素的对齐方式
app:flow_horizontalStyle = “ spread | spread_inside | packed ” 当wrapMode为chain或ALIGNED时生效
app:flow_horizontalBias = “ float " low的bias偏移,只在style为packed时生效
2.6.7、ImageFilterButton/ImageFilterView
功能很强大控件,包括圆角,图片滤镜等。
[ImageFilterButton/ImageFilterView](https://link.juejin.cn?target=https%3A%2F%2Fblog.csdn.net%2Fjavaniceyou%2Farticle%2Fdetails%2F116921501
"https://blog.csdn.net/javaniceyou/article/details/116921501")
三、代码动态修改约束及动画的实现。
比如把一个左上角的TextView,居中显示。代码如下:
1ConstraintSet constraintSet = new ConstraintSet();
2//克隆一个父布局约束,constraint就是当前父布局
3constraintSet.clone(constraint);
4//R.id.txt_1相对于父布局横向居中
5constraintSet.centerHorizontally(R.id.txt_1,ConstraintSet.PARENT_ID);
6//R.id.txt_1相对于父布局竖直居中
7constraintSet.centerVertically(R.id.txt_1,ConstraintSet.PARENT_ID);
8constraintSet.applyTo(constraint);
再看下面的解释,可能更加清楚:
1//意思R.id.view1的顶部和R.id.view2的顶部对齐
2set.connect(R.id.view1, ConstraintSet.TOP, R.id.view2, ConstraintSet.TOP)
3
4//上面就相当于XML布局里这句代码
5//app:layout_constraintTop_toTop="@+id/view2"
如果想要带动画效果去改变的话,我们只要在constraintSet.applyTo()前,加上这句代码,就会有动画效果:
1TransitionManager.beginDelayedTransition(constraint);
上面讲了一种可以代码改变,并且可以加动画效果的。接下来看,这种直接通过2个xml布局去添加约束,然后去改变。转变2个布局:
R.layout.constraint_activity_three 布局如下:
R.layout.constraint_activity_four 布局如下:
首先我们在activity里用的是R.layout.constraint_activity_three,点击按钮,让红色TextView A 和
蓝色按钮“点击改变”,通过动画变成R.layout.constraint_activity_four的样式。点击“恢复”后,又回到原来的样子。注意2个布局中,要改变约束的元素的id要保持一致,否则失效。我们看代码实现:
1public class ConstraintLayoutSecondActivity extends AppCompatActivity {
2 ConstraintLayout constraint;
3 @Override
4 protected void onCreate(@Nullable Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6 setContentView(R.layout.constraint_activity_three);
7 constraint= findViewById(R.id.constraint);
8 //改变
9 findViewById(R.id.button_change).setOnClickListener(v ->{
10 ConstraintSet constraintSet = new ConstraintSet();
11 constraintSet.clone(ConstraintLayoutSecondActivity.this,R.layout.constraint_activity_four);
12 TransitionManager.beginDelayedTransition(constraint);
13 constraintSet.applyTo(constraint);
14 });
15
16 //恢复
17 findViewById(R.id.button_reset).setOnClickListener(v->{
18 ConstraintSet constraintSet = new ConstraintSet();
19 constraintSet.clone(ConstraintLayoutSecondActivity.this,R.layout.constraint_activity_three);
20 TransitionManager.beginDelayedTransition(constraint);
21 constraintSet.applyTo(constraint);
22 });
23 }
24}
最终运行起来实现的效果如下:
四、MotionLayout
想实现如下更酷炫的效果吗:
我在B站上找了个教程,贼详细[MotionLayout教程](https://link.juejin.cn?target=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2FBV1Np4y1D7rY%3Fp%3D1
"https://www.bilibili.com/video/BV1Np4y1D7rY?p=1")
4.1、Carousel
想要实现无线循环,超强自定义动画的banner图吗?用Carousel就够了
目前都总结完了。后续有更新再补充。
推荐阅读: