ConstraintLayout 是什么
ConstraintLayout 是在2016年的 Google I/O 大会上推出的一种新型布局方式-约束布局,它可以灵活的控制组件在布局中的位置和大小,Google 为约束布局提供了配套的视图编辑器,让我们可以在可视化的界面中以拖拽的方式进行布局。可以认为 ConstraintLayout 是升级版本的 RelativeLayout,在相对布局的基础上,增加了比例这一概念,在下面的代码中将为大家详细介绍这一概念。
以下,我将会用 RL 表示RelativeLayout,CL 表示 ConstraintLayout,LL 表示 LinearLayout
我的环境
- Android Studio 版本:2.3
- ConstraintLayout 版本:com.android.support.constraint:constraint-layout:1.0.2
ConstraintLayout XML 属性
从 Android Studio 2.3 版本开始,我们创建新的布局会发现,默认的根布局已经变成了 CL
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
tools:context="com.example.xiezhen.practice.DefaultActivity">
</android.support.constraint.ConstraintLayout>
接下来,将 CL 与 RL 的属性进行比较,在了解了 CL 的基本属性后,将为大家介绍视图编辑器的中的各种操作,我会选择几种特有的操作进行讲解,相似的操作,大家可以自行练习
ConstraintLayout 和 RelativeLayout
--- | CL | RL |
---|---|---|
与目标组件左对齐 | layout_constraintLeft_toLeftOf | layout_alignLeft |
在目标组件的右边 | layout_constraintLeft_toRightOf | layout_toRightOf |
与目标组件右对齐 | layout_constraintRight_toRightOf | layout_alignRight |
在目标组件的左边 | layout_constraintRight_toLeftOf | layout_toLeftOf |
与目标组件上对齐 | layout_constraintTop_toTopOf | layout_alignTop |
在目标组件底部 | layout_constraintTop_toBottomOf | layout_below |
与目标组件下对齐 | layout_constraintBottom_toBottomOf | layout_alignBottom |
在目标组件的上部 | layout_constraintBottom_toTopOf | layout_above |
与目标组件基线对齐 | layout_constraintBaseline_toBaselineOf | layout_alignBaseline |
如上表格所示,RL的属性,CL都有,只不过在属性中多了 constraintXXX,这个部分,这部分代表 View 的边,表示View的上,下,左,右或者基线,只不过在RL中这一部分省略掉了。
在RL中,我们可以相对于父布局进行布局,例如将一个按钮与父布局的上边和左边对齐,XML 的布局代码是这样的:
在CL中是这样的:
两种方式呈现的结果都是一样的:
ConstraintLayout 的比例
在 RelativeLayout 中,我们可以使用以下三种属性来指明组件在父布局中垂直居中,水平居中或者居中
在 CL 中是这么做的
水平居中,建立与父布局左边和右边的依赖
垂直居中,建立与父布局上边和下边的依赖
下面的代码展示了一个居中的按钮
现在来讲点和 RL 不同的东西,目前为止我们展现的效果都是 RL 或者 LL 可以实现的,让我们看看 CL 的这两个属性,这两个属性的取值范围都是[0,1]
- layout_constraintHorizontal_bias
-
layout_constraintVertical_bias
其实从属性名我们也可以猜出它的作用,可以认为是在水平方向或者竖直方向上偏移的百分比,上图展示的按钮居中,是因为默认的bias属性值为0.5,下面我们改变这两个属性值,将横向的 bias 改为0.9,垂直的 bias 改为 0.1,效果如下:
ConstraintLayout 的尺寸
不同于其他组件,CL 内 View 的 layout_height 和 layout_width 有以下三种取值方式
- 指定一个具体指
- 使用 WRAP_CONTENT
- 使用 0dp,等价于 MATCH_CONSTRAINT属性
注意:没有 MATCH_PARENT 属性,我们要注意约束的概念 0dp 就代表我们的宽高将充满约束,而不是充满父布局,举个例子,我们将中间的 Button 的顶部与上方 Button 的底部约束,将中间 Button 的底部与下方 Button 的顶约束,并且将高度设置为 0dp, 期待的表现是高度充满整个约束,效果如下:
ConstraintLayout 的宽高比
以前我们经常有需求,需要满足一定宽高比的 ImageView ,CL 给我们提供了易用的属性 layout_constraintDimentionRatio 我们只需要按照 width:height 的形式填写属性值就可以了,需要注意的是layout_height,layout_width 两个属性至少有一个属性值为0dp,如果两个都是 0dp,则需要指定一个受限制的边如下图,"h,11:3",意味着高度受限,按照宽高比11:3的比例跟随宽度进行变化
ConstraintLayout chain
约束链,可以在垂直或者水平方向上提供群组行为,什么样的约束可以构成一条约束链,View 之间相互约束就可以形成链,例如下图展现一条最小的链,Button1 的底部和 Button2 的顶部相互约束
约束链的几种形式
- spread:视图均匀分布
- spread_inside :chains 中头部和尾部的视图将会将会贴在各自的约束上,其余视图将会均匀分布
- spread_with_weight:在spread 或者 spread_inside 模式中,你可以像指定 LinearLayout 的 layout_weight 属性一样来设置 CL 的 layout_constraintVertical_weight 来达到和 LinearLayout weight的同样的效果
- packed:将视图打包在一起,默认居中,我们可以通过改变 chains 的 bias属性值,来调整整条链的偏移位置
chain,可以让我们很轻松的完成线性布局可以完成的事情,并且更方便特性更强大,盗用一张官网的图帮助理解 chains style:
spread
spread_inside
spread_with_weight
packed
packed bias
GuideLine
可以认为是辅助线,作用如其名了,我们可以在容器的水平或者竖直方向插入一条辅助线,容器内的 View 都可以和辅助线建立约束,这个特性非常好用,我们先来看看 GuideLine 的几个属性
- layout_constraintGuide_begin 指定辅助线距离容器顶部或者左边的距离
- layout_constraintGuide_end 指定辅助线距离容器底部或者右边的距离
- layout_constraintGuide_percent 指定容器的宽或者高度的百分比
下面这个效果应该很常见,在中间插入一条垂直方向的 GuideLine,然后分别在 parent 右侧和 GuideLine,parent 左侧和 GuideLine 之间建立约束:
一些补充
- Percent
- Group
- Barriers
Percent
百分比布局,我们可以很容易的在 CL 中使用百分比布局,代码如下,将 layout_constraintHeight_default 设置为 percent 即采用百分比的方式布局,然后设置 layout_constraintHeight_percent 的属性值,来改变垂直方向的百分比,设置宽度百分比相同。
Group
通过 constraint_referenced_ids 属性来指定 Group 包裹的 View,对这些 View 提供统一的可见性设置,目前感觉比较鸡肋,本来我以为可以使用 Group 来提供背景色的设置,或者其他群组行为,但是很可惜,目前提供的群组行为只有可见性而已
然后将 visibility 属性设置为 Gone ,可以看见两个 Button 的约束,变成了一条 Group 约束。
Barriers
Barriers 可以理解为,在一组视图指定的边上创建一条 GuideLine。
- constraint_referenced_ids属性,指定引用的视图组
- barrierDirection属性,指定边(Barriers 的方向),有以下6种可选值 start,left,top,end,right,bottom。
如下图所示,有的时候我们可能会有类似的需求,左右两部分,左侧部分是 Title 和 Content,右侧为图像或者其他内容,如果采用 LL 和 RL 嵌套的方式,很容易解决,如果使用 CL 布局的话,我们就需要使用 Barrier 这个新特性来进行布局,在 Title 和 Content 指定为 Barrier 的引用试图组,然后在组的右边设置一条 Barrier,将图片与Barrier建立约束即可,如果不采用 Barrier ,而是直接让图片与 Title 或者 Content 建立约束,都有可能产生重叠的影响
采用 Barrier
不采用 Barrier
总结
CL 还是很容易上手的,提供的各种特性比较强大,本文虽然是采用的 XML 的形式来介绍,但其实 CL 用视图编辑器,直接采用拖拽的方式更加的便捷,CL确实是减少了视图层级,但是有没有带来效率上的提升,就见仁见智了,到底在多复杂的布局情况下适合采用 CL 官方也没有给出明确的说法,在我测试的几个布局中,CL 的性能都没有超过 RL。另外 CL 毕竟发布只有一年,个人感觉还有很多特性不够成熟,例如 Group 的特性居然只能够改变群组可见性,Barrier的特性明明可以和 Group 结合到一起,我相信CL之后会原来越完善😳。