前言
Google 在推出 Android Studio 2.2预览版时,为开发者提供了一种新的布局,那就是 ConstraintLayout 布局,当时还不是正式版。但是在最近更新到 Android Studio 2.3之后,新建一个项目,打开 MainActivity 的布局文件,你会发现根布局不再是 RelativeLayout,而是 ConstraintLayout,可见 Google 对该布局看的还是挺重的。那我们就有必要去学习一下 ConstraintLayout 布局了。
ConstraintLayout 与 RelativeLatout 很像,控件之间根据依赖关系而存在,但它比 RelativeLayout 强大的多了,简直可以说是甩 RelativeLayout 几条街。ConstraintLayout 可以有效的解决布局嵌套过多导致的性能问题,并且 ConstraintLayout 支持可视化的方式编写布局,简直是爽爆了。
使用
确保你的 Android Studio 版本是2.2或者以上。如果你的 Android Studio 版本是 2.3 正式版,那么在你创建一个新项目时,你的 Activity 布局文件的根布局默认就是 ConstraintLayout。如果 AS 版本不是 2.3,需要在你的 app/build 文件中添加 ConstraintLayout 的依赖,如下:
compile 'com.android.support.constraint:constraint-layout:1.0.2'//正式版本
打开 res/layout/activity_main.xml 文件,由于是新建的项目,As 会自动帮我们创建好一个布局,如下图所示:(注意:我使用的 AS 版本是 2.3.1)
如果你用的 AS 版本低于 2.3,你只需要将布局转换为 ConstraintLayout 即可。如下图:
我们可以看到,现在主操作界面区域内又两个类似手机屏幕的界面,左边是预览界面,右边是蓝图界面。这两个界面都可以进行布局编辑操作,区别在于左边用于预览最终的界面效果,右边部分主要用于观察控件之间的约束情况。
基本操作
ConstraintLayout 支持可视化的方式编写界面,也就是说你完全可以以拖拽的方式来完成界面的布局。比如我们在界面添加一个 TextView 控件,那么我们只需在左侧 Palette 面板上拖一个 TextView 就可以了,如图所示:
一个 TextView 已经添加到界面了,但是由于我们没有为这个控件添加约束,当程序运行时,会自动位于界面左上角。
下面我们就为这个 TextView 控件添加约束吧。每个控件的约束分为垂直和水平两类,一共可以在四个方向上为控件添加约束,如下图所示:
上图中 TextView 的上下左右各有一个圆圈,这些圆圈就是用来添加约束的,我们可以将约束添加到 ConstraintLayout 上,也可以将约束添加到另一个控件。例如:我们想让这个 TextView 位于布局的正中央,那么就可以这样添加约束,如下图:
如上图,我们在 TextView 的上下左右分别添加了约束之后,TextView 会居中央显示。如果我们想让这个 TextView 居右上角显示,我们只需在上右上添加约束即可。如下图:
这就是添加约束最基本的方法了。
除此之外,我们还可以使用约束让一个控件相对于另一个控件定位。比如说,我们再添加一个TextView,让它位于第一个 TextView 的下方,上间距为 20dp ,操作如下图:
上面的间距我们可以拖动来控制,或者通过右边的 Properties 面板控制。我更倾向于右边的 Properties 面板,它比拖动能更精确控制间距的到小。
注意:当为控件添加约束条件时,最低需要添加两个约束条件(左上、左下、右上、右下),当你添加的约束条件不满足时,在 Text 页面,你的布局 XML 中就会有报红线的控件。
知道如何添加约束后,我们该怎样删除约束呢?其实删除约束也很简单,删除约束的方式共有三中方式。第一种用于删除一个单独的约束,将鼠标悬浮在某个约束的圆圈上,该圆圈会变成红色,点击即可删除。如下图:
第二种用于删除一个控件的所有约束,选中一个控件后,会在控件左下角出现一个删除约束的图标,点击该图标,就删除了控件所有的约束条件。如下图:
第三种用于删除界面所有控件的约束条件,点击即可删除所有控件的约束条件。如下图:
Properties 面板
我们知道了如何摆放控件后,下面来看下 Properties 面板的操作。当你选中一个控件后,右边的 Properties 区域就会出现很多属性选项。如下图:
在这里我们可以设置当前控件的所有属性,如文本内容,字体大小,颜色,字体样式等等。这些功能很简单,大家点一点操作也下就会了,这里就不啰嗦了。
这里重点介绍一下 Properties 区域的上半部分,这部分也称为 Inspector。
首先可以看到,在 Inspector 中有一个纵向的轴和一个横向的轴,这两个轴也是用于确定控件的位置的。我们刚才给 TextView 的上下左右各添加了一个约束,然后 TextView 就能居中显示了,其实就是因为这里纵横轴的值都是50。如果调整了纵横轴的比例,那么 TextView 的位置也会随之改变,如下图:
不过,虽然我们将纵轴横轴的值都拖动到了 100,但是 TextView 并没有紧贴到布局的右上角,这是为什么呢?实际上,Android Studio给控件的每个方向上的约束都默认添加了一个 16dp 的间距,从 Inspector 上面也可以明显地看出来这些间距的值。如果这些默认值并不是你想要的,可以直接在Inspector上进行修改,如下图:
可以看到将上边距和右边距设置为 0 之后,TextView 就紧贴在布局的右上角了。
接下来我们来看下 Inspector 最中间的那个正方形区域,它是用来控制控件大小的一共有三种模式可选,每种模式都使用了一种不同的符号表示,点击符号即可进行切换。
-
表示 wrap_content,这个我们很熟悉了,不需要进行什么解释。
-
表示固定值,也就是给控件指定了一个固定的长度或者宽度值。
-
表示 any size,它有点类似于 match_parent,但和 match_parent 并不一样,是属于 ConstraintLayout 中特有的一种大小控制方式,下面我们来重点讲解一下。
在 ConstraintLayout 中是有 match_parent 的,只不过用的比较少,因为 ConstraintLayout 的出现就是为为了解决布局嵌套。既然没了布局嵌套,那么 match_parent 就没多大意义了。
而any size就是用于在 ConstraintLayou t中顶替 match_parent 的,先看一下我们怎样使用 any size 实现和 match_parent 同样的效果吧。比如说我想让 TextView 的宽度充满整个布局,操作如下图:
可以看到,我们把 TextView 的宽度指定成 any size,它就会自动充满充满这个布局,当然要记得把 TextView 的左右间距设置成 0 才可以。
那有的朋友可能会问了,这和 match_parent 有什么区别呢?其实最大的区别在于,match_parent 是用于填充满当前控件的父布局,而 any size 是用于填充满当前控件的约束规则。举个例子更好理解,如果我们有一个新的 TextView,它的其中一个约束是添加到当前这个 TextView 上的,那么 any size 的效果也会发生改变,如下图:
通过上图的演示,相信可以很好理解 any size 的作用了。
Guidelines (意译:指导线)
上面讲述了一些 ConstraintLayout 的基本操作,可当我们的布局过于复杂时,以上的操作可能会达不到我们的需求。下面我们来学习下 Guidelines,意译:指导线,我们可以把它理解为是一种"辅助线",就好比我们学几何图形时做的辅助线一样。在这里,我们可以添加 Vertical Guideline 和 Horizontal Guideline 两种辅助线。如图所示:
比如我们常见的登录界面,界面会有两个 Button,显示在中央。这时我们就需要添加 Vertical Guideline 辅助线,才能让这两个 Button 平分界面的宽度。如下图:
如上图,我们添加了一条 Vertical Guideline 辅助线,位置放在屏幕宽度的一半,这样两个 Button 就能平分屏幕的宽度了。上图就录制了添加 Vertical Guideline 辅助线的过程,gif太大的话会上传不了。
自动添加约束
自动添加约束的方式有两种:一种是 Autoconnect,另一种是 Inference。不过这两种方式我在开发中还是很少使用的,即使一个控件自动添加约束后,可能和我们想要的结果还是有很大差距的,所以我还是习惯手动给控件添加约束。这里就简单介绍一下吧,首先看下 Autoconnect,我们需要启用 Autoconnect 功能,默认情况下是未启动的。如下图所示:
打开 Autoconnect 功能后,它会根据我们拖放的状态自动判断如何为控件添加约束(很多情况下,还是需要手动补充添加约束条件),比如我们将 Button 拖放到界面的正中央,那么控件的上下左右都会自动添加上约束。如下图所示:
然后我们在 Button 下面再放一个 Button,效果如下:
可以看到,添加的 Button 只有左右自动添加了约束,此时还需要手动添加一个约束,控件才能正常显示。Autoconnect 不能完全明白我们的意图。总之,如果你感觉 Autoconnect 方便的话,可以把它当成一种辅助,但并不能完全靠它添加约束。
我们再来看下另一种自动添加约束的功能 Inference,它比 Autoconnect 的功能更加强大。因为 Autoconnect 是给当前操作的控件自动添加约束,而 Inference 是为当前界面所有的控件添加约束。因此,Inference 比较适合用来实现复杂度较高的界面。
下面通过一个例子演示 Inference 的用法。当前界面有两个 TextInputLayout,和一个 Button 按钮,我们使用 Inference 来意见生成约束。如下图所示:
好了,这里介绍了 ConstraintLayout 的一些基本用法,通过本片文章的介绍,相信你对 ConstraintLayout 有了深入的认识。还有就是 ConstraintLayout 的 Chains 功能,我目前也正在研究,下面给出关于 Chains 文章的链接:https://blog.stylingandroid.com/constraintlayout-chains-spread-chains/ 。
目前 ConstraintLayout 版本才到 1.0.2,后续可能会出很多的功能,让我们拭目以待吧。