Android ConstraintLayout详解
本文作者
本文由_小河马投稿。
_小河马的博客地址:
http://www.jianshu.com/u/14354bcb0e09
ConstraintLayout可能大家也比较熟悉了,在Google I/O 2016 上发布了 ConstraintLayout,也就是Android Studio 2.2中发布的新功能。
以前我们写布局的时候基本都是靠编写XML,遇到复杂的布局避免不了多层嵌套,不可避免的会影响 UI 界面绘制的效率。
目前对于复杂的界面,使用 RelativeLayout也无法解决,ConstraintLayout可谓RelativeLayout的升级版,但是要比前者强大太多。
Constraint翻译为约束,ConstraintLayout就是在子 View 上添加各种约束条件来控制每个子View所在的位置以及显示的尺寸。
而且这一切都是通过可视化操作来实现的。
当然,可视化操作的背后仍然还是使用的XML代码来实现的,只不过这些一切都是AS自动生成的
升级Android Studio到2.3你会发现新建的XML根布局从以前的RelativeLayout变成了ConstraintLayout,可见Google对这个控件的重视,这也值得我们去学习。
ConstraintLayout 官方样例代码
https://github.com/googlecodelabs/constraint-layout
ConstraintLayout Google官方文档
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html
此界面是基于Android Studio 2.3的截图,相对与2.2很多图标做了改变,其中这几个主题区域是没变的:
Palette是控件区域,所有系统View和Layout都在这里,可以分类查找。也可以直接搜索拖入布局中
Component Tree当前布局的层级结构,当点击一个View的时候就会选中这个View
这里是对选中的View编辑操作的工具栏
Design Editor 布局编辑器主窗口,可以通过点击左下Design和Text切换编辑模式
Properties可以修改当前选中View的各种属性。点击下面的图标可以查看更多的View属性
约束帮助你保持控件对齐, 你可以使用锚点来确定各控件之间的对齐规则,要创建一个约束, 你需要在指定手柄上点击并按住鼠标, 然后拖到另一个控件的约束手柄. 一旦锚点变绿, 就可以松开鼠标完成约束创建。
这样就创建了一个简单的约束,BUTTON2位于BUTTON1下49dp的位置,这样BUTTON2的水平位置不会变,垂直位置就始终在BUTTON1下49dp处了不管BUTTON1如何移动。
现在我们想BUTTON2 水平和垂直位置都随着BUTTON1的位置改变而改变呢,我们需要添加新的约束,如下图
从图中我们可以看到BUTTON2的位置完全受BUTTON1的约束。
有很多常用的约束在顶部的工具栏中直接使用,用鼠标选中需要约束的控件然后在工具栏选择约束类型。
在增加一个BUTTON3,要让BUTTON2和BUTTON3和BUTTON1的右边对齐。
要让BUTTON2和BUTTON3和BUTTON1的顶部对齐
可以看到选择了约束模型后会自动创建好每一个View的约束,还有其他很多模型应该看图标就能看明白是怎么样的,我就不一一示范了(懒)。约束对象不仅可以是View也可以说是父布局。
基线约束
还有一种基线约束,其意为控件之间的文本基线约束。换句话说就是文本对齐,当然这种这种约束是有文本控件才有的约束,Layout是没有基线约束的。
创建基线约束只需要选中控件然后点击左下角的第二个图标就会出现控件的基线,然后链接所需要对齐的其他控件就可以了
使用自动连接创建约束 Autoconnect
在工具栏有一个磁铁都一样图标
这个就是开启或关闭自动约束的开关,也叫Autoconnect 默认是开启的。Autoconnect会判断我们的意图,并自动给控件添加约束。
不过Autoconnect是无法保证百分百准确判断出我们的意图的,如果自动添加的约束并不是你想要的话,还可以在任何时候进行手动修改。可以把它当成一个辅助工具,但不能完全靠它去添加控件的约,使用起来也很有局限性。
如下图所示:
使用推理操作创建约束 Inference
Inference也是用于自动添加约束的,但它比Autoconnect的功能要更为强大,使用起来也很方便。
因为AutoConnect只能给当前操作的控件自动添加约束,而Inference会给当前界面中的所有元素自动添加约束。可以一键自动生成所有控件的约束。
如下图所示
删除约束
控件分别有四个方向上的约束点,四个角的正方形图标拖动可以改变控件的大小。要删除约束也很简单,选中控件后点击坐下角的图标就删除了当前控件的所以约束,点击某一个约束的原点可以删除单个约束
当然你也可以点击工具栏的上如下图的图标,那么会清除布局中所有的约束
当我们选中某个控件后那么视图的右边则是当前控件可以设置的属性栏。一些基本的属性设置这里就不讲解了,主要了解下如图所示的区域如何使用,这部分也叫Inspector 这部分就是来控制控件的宽高以及Margins值。
相对约束定位控件
当一个控件上有至少两个对立的连接时, 比如上和下, 或者左和右, 你可以看到一个可以让你沿着对立连接的轴调整控件位置的滑块. 这也被称为横向或纵向偏量. 如下图
拖动滑块可以改变控件的横向或者或者纵向的偏移量. 另外也可以通过移动控件到目标目标位置实现这一点。
控件宽高尺寸
空间的宽高可以通过单击下图中的线来控制控件宽高
宽高有以下选项
Fixed: 此选项允许你指定控件的高和宽.
AnySize: 此选项让控件占用所有可用空间以适应约束. 换句话说, 这更像是匹配约束. 与 match_parent 不同, 后者占用父 View 的所有可用空间.
Wrap Content: 这个就是以前XML布局的Wrap Content是相同的
注意AnySize和 match_parent 有所不同,如果 左边的ImageView 约束于右边的 Button, 设置为AnySize 只会扩展它适应 右边的button ,通过下面这张图应该就很好理解了。
点击外围的线可以调整控件的Margins值。
Guidelines可以帮助你在添加约束布局的时候更方便的确定控件的位置,可以创建垂直或者水平方向的Guidelines,创建后可以点击选择Guidelines位置的方式,默认是距离左边多少dp,点击后可以切位为距离右边的距离和屏幕的百分比距离
如果我们要两个按钮水平居中就需要用到Guidelines
可以看到我们给左边的按钮添加了约束,距离底部24dp 右边约束于Guidelines,右边的按钮则左边约束于Guidelines而顶部则于左边按钮对齐,这样两个按钮就水平居中对齐了。
Chains 是最新才加入的一个新功能。 Chains 为同一个方向(水平或者垂直)上的多个子View 提供一个类似群组的概念。
其他的方向则可以单独控制。Chain 的属性由该群组的第一个 View 上的属性所控制(第一个 View 被称之为 Chain head)。
首先我们创建一个水平方向的Chain,通过工具栏我们可以快速的创建一个Chain
可以看到我们快速的创建了一个Chain约束,Chain 的属性由该群组的第一个View也就是Chain head 上的属性所控制 。
Chain head有很多属性如下
layout_constraintHorizontal_chainStyle
layout_constraintHorizontal_weight
layout_constraintVertical_chainStyle
layout_constraintVertical_weight
chainStyle 是设置到 Chain Head 上的,指定不同的 style 会改变里面所有 View 的布局方式,有如下四种 Style:
CHAIN_SPREAD 这个是默认的 Style, 里面的所有 View 会分散开布局
Weighted chain,在 CHAIN_SPREAD 模式下,如果有些 View 的尺寸设置为 MATCH_CONSTRAINT(0dp),则这些View 尺寸会占据所有剩余可用的空间,和LinearLayout weight 类似。
CHAIN_SPREAD_INSIDE 和 CHAIN_SPREAD 类似,只不过两端的两个 View和 父容器直接不占用多余空间,多余空间在 子View 之间分散
CHAIN_PACKED这种模式下,所有的子View都 居中聚集在一起,但是可以设置bias 属性来控制聚集的位置。
如果多个子View尺寸设置为 MATCH_CONSTRAINT(0dp),则这些 View 会平均的占用多余的空间。
通过layout_constraintHorizontal_weight或layout_constraintVertical_weight属性,可以控制每个View所占用的多余空间的比例。
例如,对于只有两个 View的一个水平Chain,如果每个View 的宽度都设置为MATCH_CONSTRAINT, 第一个View的 weight为 2;第二个View 的weight 为 1,则第一个View所占用的空间是 第二个 View 的两倍。(以上其实就是官方文档翻译过来的)。
比如我们现在想在界面上水平放置三个按钮,这三个按钮均分父容器宽度,且每个按钮的间距为8dp,首先我们就要设置Chain head的chainStyle为spread并且layout_constraintHorizontal_weight设置为1
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintHorizontal_weight="1"
给剩余两个按钮添加
app:layout_constraintHorizontal_weight="1"
并且把按钮的宽度都设置为0dp然后修改margin值
当我们修改最后一个按钮的layout_constraintHorizontal_weight为2的时候可以看到如下图
可以看到最后一个按钮的宽度是变成了前两个按钮的两倍,说明这个layout_constraintHorizontal_weight和LinearLayout的weight类似。
修改第一个按钮的layout_constraintHorizontal_chainStyle为packed你会发现layout_constraintHorizontal_weight没有作用了,按钮宽度需要重新修改为wrap_content或者固定值。
两边按钮的位置可以通过Bias调节,中间的按钮可以调节margin值
最后需要注意的是每个控件都必须有上下左右的约束,这样才能确实控件在布局中的准确位置。
在右上角的红色角标标识了当前有多少错误,错误一般都是控件没有某一个方向的约束,当然也可以在XML中查看错误信息
相信现在用ConstraintLayout去做一个复杂布局应该难不到你了,各种约束也可以满足各种样式的布局,Android Studio 2.3发布后ConstraintLayout已经成为了默认的根布局可以看出它的发展前途, ConstraintLayout简直是要变革 Android 写界面方式啊,更简便更高效!
THE END !
现在能用 ConstraintLayout 做些什么?
https://realm.io/cn/news/constraintlayout-it-can-do-what-now/
如果你有想学习的文章直接留言,我会整理征稿。如果你有好的文章想和大家分享欢迎投稿,直接向我投递文章链接即可。
欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号: