ConstraintLayout介绍

介绍ConstrainLayout

ConstraintLayout

1.为什么用ConstraintLayout

1.1 减少嵌套,加速界面渲染

ConstraintLayout的基本使用方式就是这些, 兼顾LinearLayout与RelativeLayout的优点, 非常适合构建复杂布局, 降低布局的层级, 优化布局,加快渲染速度。

1.2 提供很多约束属性多,开发效率高

ConstraintLayout的属性有很多,有很多种约束属性, 熟悉之后可以高效完成界面搭建。

1.3 有助于界面的适配

传统Layout经常会遇到界面在不同机型界面不统一的问题,ConstraintLayout可以配合一些辅助控件像GuideLine的百分比(app:layout_constraintGuide_percent="0.5")来对屏幕的水平和竖直方向做分割,在利用ConstraintLayout的属性对控件进行约束,可以达到让界面适配的效果。

2.ConstraintLayout入门

2.1 常用约束

公式:

1
layout_constraint[本源控件要做约束位置]_to[目标控件相对的位置]="[目标控件ID]"

本源控件要做约束位置与目标控件的相对位置不能是随意的,是要在同一个方向上的位置,例如Bottom_toBottomOf,Top_toBottomOf, Bottom_toTopOfTop_toTopOf是垂直方向上的一组约束,没有Top_toStart这样的约束。

20171031150945732850740.png

垂直方向有三个约束位置:Top, Bottom, BaseLine

水平方向有两个约束位置:Start(Left), End(Right)

可用的约束,可以搭配layout_[位置]做一些基础和复杂的布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
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

2.2 居中

ConstraintLayout的居中是个比较不明显的功能,水平方向的居中,要对居中的控件start(left)end(right)两个位置做好约束,垂直方向的居中要对控件topbottom两个位置做约束就可以达到控件在约束区域的居中效果。如下

1
2
3
4
5
6
7
8
9
<ImageView
android:id="@+id/imageView2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="117dp"
android:layout_height="143dp"
app:srcCompat="@drawable/icon_android_bg"/>

20171101150954763071757.png

2.3 match_parent要用0dp来替代

ConstraintLayout中de控件如果宽高要设置成match_parent需要设置成0dp(官方建议,也可以设置成match_parent,但是有些情况下match_parent会不生效)。设置成0dp也需要配合相对方向的约束。

1
2
3
4
5
6
7
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="64dp"
android:text="注册"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

20171101150954786245526.png

2.4一些高级用法

1.GONE与Margin

有可能会遇到一个情况是,目标控件有可能会被设置为GONE,这时候约束还是存在,界面有可能会产生不整齐的问题,这时候就可以用layout_goneMargin来重新设置margin。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="BTN1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BTN2"
app:layout_constraintStart_toStartOf="@id/button1"
app:layout_constraintTop_toBottomOf="@id/button1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:text="BTN3"
app:layout_constraintStart_toEndOf="@id/button2"
app:layout_constraintTop_toTopOf="@id/button2" />

20171105150988782494038.png

button2设置GONE后,约束还在,btn3与左边间距还是50,导致界面不美观:

2017110515098878884334.png

1
2
3
4
5
6
7
8
9
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
//在Button设置goneMarginStart表示左边控件Gone掉的话采用新的margine
app:layout_goneMarginStart="0dp"
android:text="BTN3"
app:layout_constraintStart_toEndOf="@id/button2"
app:layout_constraintTop_toTopOf="@id/button2" />

20171105150988805696462.png

2.Chain链式(主要是为了替代LinearLayout)

有一种情况是需要等分显示布局,一般用的是LinearLayout,在ConstraintLayout里面主要是要用Chain来完成平分。各个布局之前都要做一个相对的约束。即各个布局之间都要做相互的约束。

2017103115094573196056.png

A与B做水平的平分,则A与B要做相互约束就能产生Chain:

1
2
3
4
5
6
7
8
<!--伪代码-->
<!--A控件-->
start_toStartOf="parent"
end_toStartOf="B" //对B约束
<!--B控件-->
start_toEndOf="A" //对A约束
end_toEndOf="parent"

并且可以通过layout_constraintHorizontal_chainStyle 或者layout_constraintVertical_chainStyle在平分的第一个控件设置水平或者垂直方向上Chain的方式:

20171031150945730476198.png

3.GuideLine

GuideLine主要是可以创建一条基准线,用来做一个百分比,或者固定值的控件,用法有很多,在适配上面有好的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<android.support.constraint.Guideline
android:id="@+id/guideline_v"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.6"/>
<com.botasky.cyberblack.view.ScanView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="@id/guideline_v"/>

20171105150988716083952.png

上面的GuideLine就可以让自定义View,ScanView(或者其他的原生控件和自定义View)的height不管在任何屏幕下所占的高度都是主屏幕的60%。与传统的写死高度相比,用GuideLine可以让适配方案不在变得复杂。

ConstraintLayout上手建议

1.尽量不要用手托控件去对控件做约束,而是用纯手打的方式去写约束

AndroidStudio的手托控件功能很鸡肋,没有像Xcode的XIB那样强大,手托控件造成的一个问题是你可能会不理解Constraint的约束原理,并且手托控件会造成IDE生成一些让人琢磨不透的代码。

2.协同开发AndroidStuido版本要统一

开发过程中遇到过因为AndroidStudio版本不统一导致其他的开发队员拉取代码后出现XML代码会自动删除一些margin的代码,并且生成一些没有意义的布局代码,导致在低版本下面布局会错乱的问题。建议开发中把IDE升级到AndroidStudio3.0,对ConstraintLayout的支持会比较稳定。并且将ConstraintLayout的版本升到最新,目前最新版本是1.1.0-beta3

1
2
3
4
5
6
7
8
<ImageView
android:id="@+id/imageView2"
android:layout_width="117dp"
android:layout_height="143dp"
app:srcCompat="@drawable/icon_android_bg"
//生成的无意义的代码
tools:layout_editor_absoluteX="122dp"
tools:layout_editor_absoluteY="312dp" />