[Android] ConstraintLayout

最近把 AS 升级了一下,发现新建项目 Activity 默认使用了 ConstraintLayout 这个布局,于是赶紧搜索了一下,发现这个ConstraintLayout 与其说是一个布局,不如说是一种新的可视化编辑布局文件方式。AS 此前并不实用的可视化布局编辑方式,在有了 ConstraintLayout 后,可以成为一种新的选择。虽然在实际应用场景下还存在不少掣肘,但是除了可视化的编写方式可以大大提升的开发速度之外,对某些传统写法需要多层嵌套才能实现的布局也不失为另外一种解决方式。

基本使用

创建布局

在 AS2.3 以上版本只需直接新建项目,选择 EmptyActivity 即可,AS 会默认使用 ConstraintLayout 作为布局。低版本下,需要添加依赖:

  compile 'com.android.support.constraint:constraint-layout:1.0.2'

并且在xml文件的可视化编辑页面,在布局上右键,转化为 ConstraintLayout 。

将布局转化为 ConstraintLayout

成功创建布局后在左上角选择相应控件拉到布局中即可。

基本操作

当我们把控件拉布局中,控件会变成下图这样的状态:

基本操作

我们可以看到四边上分别有一个空心的圆点,四个角分别有一个方点,控件下紧贴着两个可操作的按钮。

添加约束.gif

边上这四个圆点是最重要的,用于添加约束。按着它不放,可以拉出一个带箭头的线,这条线叫做约束(Constraint),当箭头碰到父布局的边或者其他控件四边上的空心圆时就会吸附上去,同时可以马上看到控件向箭头指定的边对齐。

改变控件大小.gif

四角上的方点用于改变控件大小。

文字基准线约束.gif

控件下有 ab 字样的按钮用于添加文字基准线约束,只有带文字的控件才会出现这个按钮,且该约束也只能指向另一个带文字控件的文字基准线。

删除控件所有约束.gif

最后一个带有叉叉的按钮用于删除该控件的所有约束。
另外删除约束还有两种方式:

删除单个约束 :删除页面所有约束.gif

点击已经添加约束的圆点,可以删除单个约束。上方工具栏的 clear all constraint 按钮则可以删除整个页面所有约束。

约束解析

我们现在添加一个 Button 到布局里,只为其添加水平上指向父布局右边的约束,然后运行。


添加单方向约束.gif

可以看到结果虽然水平方向是向屏幕右边对齐了,但是垂直方向却和预览不同。ConstraintLayout 的可视化编辑并没有看起来那么神奇,实际上只是 AS 为我们自动写入 xml 代码而已,看一下 AS 生成的代码会发现 ConstraintLayout 其实和 RelativeLayout 非常相似,主要也是靠其他控件或者父布局的相对位置来实现定位。
像上面那个例子,我们只指定了水平方向上的约束,垂直方向 AS 上并没有生成相应代码,所以控件的垂直位置会默认对齐父布局的上边(相应的水平方向会对齐左边)。打开其 xml 代码,我们可以看见,刚才添加的约束,实际上生成了这样一句代码:

app:layout_constraintRight_toRightOf="parent"

可以看出其实约束的具体代码格式是这样:app:layout_constraintXxx_toXxxOf="xxxxx"
这个 ConstraintLayout 独有的属性,可以先简单理解为控件的某一边向目标控件的某一边对齐。和RelativeLayout 的 layout_alignXxx 相对控件对齐属性比较接近,而且toXxxOf多了目标控件的方向的指定,所以更加强大,还可以实现 RelativeLayout 的相对控件并列、相对父布局居中等效果,甚至可以实现 RelativeLayout 做不到的控件居中排列。
在水平或垂直方向上指定一个方向的约束可以理解为向某边对齐,同方向上同时指定反向两个约束则可以理解为在两边之间居中。如下图:

居中.gif

上图将控件的四边约束指向父布局的四边,使得控件在父布局的水平和垂直方向上居中,从而实现相对整个父布局居中的效果。

相对控件居中.gif

相对控件居中也是一样的方法。

Guideline

约束除了可以指向父布局和其他控件的四边之外,还可以指向Guideline。Guideline是一个不显示的View,类似于布局的参考线,通过Guideline可以实现让控件的约束指向父布局高度的 50%、25%之类比较常见的需求。

Guideline.gif

点击预览上方的 Guideline 按钮,然后选择 Guideline 的方向,Guideline就会自动添加到布局中。Guideline显示的参考数值有 3 个模式,默认是距离父布局上或左边的距离,还有相对另一边距离,在方向上的百分比。通过点击其左或上端的圆形按钮,可以循环切换三种模式。

bias和margin

除了对齐和居中,其他精细的定位主要通过 bias 和 margin 来实现。

指定margin的两种方式.gif

指定margin主要有两种方式,第一种是添加对齐约束后(不能是居中约束)直接拉动控件到合适距离,第二种是在右边的 properties 栏中直接指定。
需要注意的是在 ConstraintLayout 中 margin 不是指该控件和其他控件或者父布局某边的距离,而是指该控件与指定了约束的某条线的距离。所以控件间相对某边对齐,需要注意把某边的margin调整为0。

bias.gif

另外设置了居中约束的控件,可以通过拉动properties 栏四边上的滑块,或者直接拉动控件来调整 bias。
bias 可以理解为控件在反向两个约束的偏移距离,默认值是 0.5,调整到 0 或 1 时会完全对齐其中一边。

chain

ConstraintLayout 还提供了一个叫做 chain 的属性。该属性可以在同一个轴上(水平或者垂直)为多个控件提供一个类似群组的统一表现。另一个轴可以单独控制。

chain.gif

选中多个控件后,点击工具栏上的 Center Vertically,或者Center Horizontally 按钮,可以看到控件间出现了锁链状的连线和一个锁链按钮。点击锁链按钮,可以切换控件组在指定的轴上的分布形式。

控件尺寸

控件尺寸除了可以拉动控件四角改变之外,还可以在 properties 栏上编辑。


控件尺寸.gif

可以看到在最中间的那个正方形区域可以改变控件的宽高的模式:

表示wrap content

表示固定值

表示any size

另外 match parent 虽然在 ConstraintLayout 中依然有效,但是 ConstraintLayout 的一大特色就是减少嵌套,所以不太用到,与之类似的就是 any size 属性。any size和 match parent 的区别在于,match parent是用于填充满当前控件的父布局,而any size是用于填充满当前控件的约束规则。所以约束规则改变时,控件的大小也会改变。


any size.gif

上面的例子中,上方的 Button 约束指向父布局上边和另一个 Button,当另一个 Button 发生变化时,上方 Button的约束也发生了变化,同时高度也随之变化。

可视化编辑界面简介

可视化编写布局比较容易上手,基本上了解一下整个界面,自己试一试就明白了,所以这里对整个界面进行一点介绍。
ConstraintLayout 的可视化编辑界面主要分为五个部分:


可视化编辑界面
  • 1 Palette 用于选择控件,左边列是控件的分类,右列是控件列表,下面是控件的预览。
  • 2 Component Tree,显示当前布局包含所有控件。
  • 3 工具栏,其中有对齐控件、智能添加约束等用于快速编辑布局的功能按钮。
  • 4 编辑窗口。
  • 5 Properties,用于设定选中控件的各种属性。注意上方有一个放大镜按钮,可以用来搜索控件属性。

特别提一下,工具栏上有一个Infer Constraints (智能添加约束)按钮,这个功能比较好用。


智能添加约束.gif

只需要在编辑窗口把控件摆好,然后点一下 Infer Constraints 按钮,就可以看到所有控件的约束都已经自动添加好了。

引入自定义View

添加自定义View.gif

在上图的例子里我提前添加了比较常用的 RecyclerView 的依赖,然后在 Component Tree 中选中 Advanced
分类,把 view 拖拽到编辑窗口中,会出现项目可用的所有View。直接选中所需 View,或者直接输入 view 的名称进行搜索也可以。

总结

ConstraintLayout 在上手之后速度明显要比传统的布局编写方式快上不少,减少嵌套效果明显。虽然现在还存在一些问题,维护起来也感觉比较麻烦,在项目中作为主要方式使用可能还不太现实。但是平时写写 Demo 用起来还是不错的,针对部分布局用来减少嵌套也是个不错的选择。
不管如何,其作为 Google 在去年的I/O大会上强推一个功能,现在更是作为 AS 的默认布局,还是有先了解熟悉一下的必要。

本文主要参考文章:
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html
http://blog.csdn.net/guolin_blog/article/details/53122387
http://www.jianshu.com/p/beb9f7157209

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容