2016年google就已经公布了这个约束布局ConstraintLayout。
但是时至现在2018年,还是很多人在使用普遍的LinearLayout或者RelativeLayout。有的可能会用到百分比布局,但是还是很少很少用到。我觉得非常有必要普及这方面的内容,并且这个对于提高性能,是有作用的
唯一副作用是学习成本高、相对于其他普通布局完成的速度可能也会慢
我最近也开始涉及学习这方面,发现确实如果不通过好好的例子来写的,确实很难上手。
所以出了以下内容,让大家更快更容易了解!
首先先跟大家共享我搜到的文章:
https://blog.csdn.net/lmj623565791/article/details/78011599?utm_source=tuicool&utm_medium=referral
https://blog.csdn.net/guolin_blog/article/details/53122387
https://segmentfault.com/a/1190000009536640?utm_source=tuicool&utm_medium=referral
再列出我觉得有参考性的demo,github上找的
https://github.com/googlesamples/android-ConstraintLayoutExamples
https://github.com/vtthach/20170704_Sample_ConstraintLayout
属性作用:
以前RelativeLayout的约束有两种:
- 1 子控件和子控件之间的约束(如android:layout_below="@id/title")
- 2 子控件和父控件的约束(如 android:layout_alignParentTop="true")
- 3 子控件和Guideline(参考线)的约束。下面会讲解参考线的作用。
参数取值是 ID(@id/button1)代表约束1、3, 或者 字符串"parent" 代表约束2:
RelativeLayout 对应父类 | RelativeLayout 对应其他view | ConstraintLayout | |
---|---|---|---|
android:layout_alignParentLeft="true" | android:layout_alignLeft | app:layout_constraintLeft_toLeftOf | 与指定View的左边界一致 |
android:layout_alignParentStart="true" | android:layout_alignStart | app:layout_constraintStart_toStartOf | |
android:layout_alignParentTop="true" | android:layout_alignTop | app:layout_constraintTop_toTopOf | 与指定View的上边界一致 |
android:layout_alignParentRight="true" | android:layout_alignRight | app:layout_constraintRight_toRightOf | |
android:layout_alignParentEnd="true" | android:layout_alignEnd | app:layout_constraintEnd_toEndOf | |
android:layout_alignParentBottom="true" | android:layout_alignBottom | app:layout_constraintBottom_toBottomOf | 与指定View的下边界一致 |
android:layout_centerHorizontal="true" | app:layout_constraintStart_toStartOf="parent" 和 app:layout_constraintEnd_toEndOf="parent" | ||
android:layout_centerVertical="true" | app:layout_constraintTop_toTopOf="parent" 和 app:layout_constraintBottom_toBottomOf="parent" | ||
android:layout_centerInParent="true" | app:layout_constraintStart_toStartOf="parent", app:layout_constraintTop_toTopOf="parent", app:layout_constraintEnd_toEndOf="parent", 和 app:layout_constraintBottom_toBottomOf="parent" | ||
android:layout_below | app:layout_constraintTop_toBottomOf | 在指定View的下方 | |
android:layout_toEndOf | app:layout_constraintStart_toEndOf | 在指定View的右边 | |
android:layout_toRightOf | app:layout_constraintLeft_toRightOf | 在指定View的右边 | |
android:layout_above | app:layout_constraintBottom_toTopOf | 在指定View的上方 | |
android:layout_toStartOf | app:layout_constraintEnd_toStartOf | 在指定View的左边 | |
android:layout_toLeftOf | app:layout_constraintRight_toLeftOf | 在指定View的左边 | |
android:layout_alignBaseline | app:layout_constraintBaseline_toBaselineOf |
组合属性作用:
ConstraintLayout 组合属性 | 解释 |
---|---|
app:layout_constraintEnd_toStartOf="@+id/vLine", app:layout_constraintTop_toTopOf="@+id/vLine", app:layout_constraintBottom_toBottomOf="@+id/vLine" | 这个是基于vLine控件的左边,并且完全的中心对齐 |
app:layout_constraintBottom_toBottomOf="@+id/vLine" app:layout_constraintStart_toEndOf="@+id/vLine" app:layout_constraintTop_toTopOf="@+id/vLine" | 同上,这次是在右边并且中心对齐 |
1.首先完成顶部第一个图片:
image.png添加以下两个属性
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
即可完成居中,因为左边约束了,右边也约束了。可以通俗的理解为左边和右边用相同的力道(我这样说是因为下面会介绍可以控制哪边用的力道大小)都相扯约束,自然居中了。
如果第一个图片不添加
app:layout_constraintTop_toTopOf="parent"
则这个相距属性android:layout_marginTop="16dp"是不会触发的。
所以总结第一个图片:
<ImageView
android:id="@+id/imgIcon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:src="@drawable/ic_security_lock"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
2.接着完成顶部第二个控件:
image.png首先直奔主题,关键的一个属性:
layout_constraintTop_toBottomOf
按照我的理解则是约束上面并且位于该约束控件的下面
同时为了居中,也是添加约束父布局的左边和右边,所以最终是
<TextView
android:id="@+id/txtMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/please_enter_your_4_bit_password"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgIcon" />
3.接着是比较困难的第三个控件布局
image.png首先我们按照上面所了解的,先分别添加4个控件
image.png
第一个控件,居左并且在第二个控件的下面。第二个控件在第一个控件和第三个控件的中间,第三个控件一样,只有最后一个第四个控件在最右边。
<ImageView
android:id="@+id/imgOne"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="24dp"
android:src="@drawable/pin_code_round_empty"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtMessage"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/imgTwo"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="24dp"
android:src="@drawable/pin_code_round_empty"
app:layout_constraintLeft_toRightOf="@+id/imgThree"
app:layout_constraintRight_toLeftOf="@+id/imgOne"
app:layout_constraintTop_toBottomOf="@+id/txtMessage"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/imgThree"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="24dp"
android:src="@drawable/pin_code_round_empty"
app:layout_constraintLeft_toRightOf="@+id/imgTwo"
app:layout_constraintRight_toLeftOf="@+id/imgFour"
app:layout_constraintTop_toBottomOf="@+id/txtMessage"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/imgFour"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="24dp"
android:src="@drawable/pin_code_round_empty"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtMessage"
tools:ignore="ContentDescription" />
那么剩下一个问题如何让他们居中呢?很简单,第一个控件添加
app:layout_constraintRight_toLeftOf="@+id/imgFour"
大意是居左,跟右边的第四个控件约束,变成这样
image.png
然后第四个控件添加该属性
app:layout_constraintLeft_toRightOf="@+id/imgOne"
最终便可以居中了
4.接着是下面的百分比布局
首先完成百分比布局之前,我们需要先明确大体布局。如上面的布局,横布局需要分成三等份,竖布局需要分成四等份。然后就开始创建参考线了。
4.1首先为了铺满这个百分比,要先创建多一个ConstraintLayout布局,基于txtForget控件的下面。
<android.support.constraint.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtForget">
4.2开始创建参考线。
Preview创建Guideline创建竖线3条
<android.support.constraint.Guideline
android:id="@+id/guidelineV33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.33333333" />
<android.support.constraint.Guideline
android:id="@+id/guidelineV66"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.66666666" />
<android.support.constraint.Guideline
android:id="@+id/guidelineV100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="1" />
创建横线4条
<android.support.constraint.Guideline
android:id="@+id/guideline1H25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.25" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.50" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.75" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="1" />
创建完所需要的参考线之后如图所示:
image.png4.3接下来我们只要负责把需要放的控件放进参考线里面居中即可
让我们看看最重要的4个属性
app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
app:layout_constraintEnd_toStartOf="@+id/guidelineV33"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf:表示与指定View的左边界一致,如果是parent则是父控件最左边
app:layout_constraintEnd_toStartOf:在指定View的左边
app:layout_constraintBottom_toTopOf:在指定View的上方
app:layout_constraintTop_toTopOf:与指定View的上边界一致,如果是parent则是父控件的最上边
那么把每个控件都放进去,最终百分比的代码:
<android.support.constraint.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtForget">
<TextView
android:id="@+id/txtOne"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_margin="8dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:tag="1"
android:text="1"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
app:layout_constraintEnd_toStartOf="@+id/guidelineV33"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/txtTwo"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_margin="8dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:tag="2"
android:text="2"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
app:layout_constraintEnd_toStartOf="@+id/guidelineV66"
app:layout_constraintStart_toEndOf="@+id/txtOne"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/txtThree"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_margin="8dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:tag="3"
android:text="3"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
app:layout_constraintEnd_toStartOf="@+id/guidelineV100"
app:layout_constraintStart_toStartOf="@+id/guidelineV66"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/txtFour"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_margin="8dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:tag="4"
android:text="4"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="@+id/guideline1H50"
app:layout_constraintEnd_toStartOf="@+id/guidelineV33"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline1H25"
tools:ignore="HardcodedText" />
<android.support.constraint.Guideline
android:id="@+id/guidelineV33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.33333333" />
<android.support.constraint.Guideline
android:id="@+id/guidelineV66"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.66666666" />
<android.support.constraint.Guideline
android:id="@+id/guidelineV100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="1" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.25" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.50" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.75" />
<android.support.constraint.Guideline
android:id="@+id/guideline1H100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="1" />
</android.support.constraint.ConstraintLayout>
image.png
请注意,app:layout_constraintStart_toStartOf和app:layout_constraintLeft_toLeftOf有区别的,具体可以在改演示中的百分比修改就知道具体区别了。
5、利用Barrier完美实现“多对象约束”
例子布局类似这样的布局,中间这条线是在左边两个文本框以及右边两个文本框的中间。广州黄埔的文字或者江苏南京的文字如果过长,中间的一条线都会往下移动,例如这样:
image.png
或者这样:
image.png
那么如何把这两个TextView对象当成一个对象来看待呢,很简单,如下代码:
<android.support.constraint.Barrier
android:id="@+id/barrier7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="tvDeparture,tvDestination" />
最后把这个Barrier当成一个对象对待即可
app:layout_constraintTop_toBottomOf="@+id/barrier7"
6、待编辑的其他属性
-
Barrier
Barrier是一个虚拟的辅助控件,它可以阻止一个或者多个控件越过自己,就像一个屏障一样。当某个控件要越过自己的时候,Barrier会自动移动,避免自己被覆盖。 -
Group
Group帮助你对一组控件进行设置。最常见的情况是控制一组控件的visibility。你只需把控件的id添加到Group,就能同时对里面的所有控件进行操作(比如批量隐藏,删除等等)。
<android.support.constraint.ConstraintLayout ...>
<TextView
android:id="@+id/text1" ... />
<TextView
android:id="@+id/text2" ... />
<android.support.constraint.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids=”text1,text2" />
</android.support.constraint.ConstraintLayout>
- Circular positioning
可以相对另一个控件,以角度和距离定义当前控件的位置,即提供了在圆上定义控件位置的能力。如图所示:
[图片上传失败...(image-e0b4d2-1523179128704)]
- Placeholder
Placeholder顾名思义,就是用来一个占位的东西,它可以把自己的内容设置为ConstraintLayout内的其它view。因此它用来写布局的模版,也可以用来动态修改UI的内容。
总而言之,约束布局的能力正在变得越来越强大。
网友评论