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 官方样例代码
ConstraintLayout Google官方文档
布局编辑器功能介绍
此界面是基于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
会判断我们的意图,并自动给控件添加约束。不过Autoconnec
t是无法保证百分百准确判断出我们的意图的,如果自动添加的约束并不是你想要的话,还可以在任何时候进行手动修改。可以把它当成一个辅助工具,但不能完全靠它去添加控件的约,使用起来也很有局限性。 如下图所示
使用推理操作创建约束 Inference
Inference
也是用于自动添加约束的,但它比Autoconnect
的功能要更为强大,使用起来也很方便。因为AutoConnect
只能给当前操作的控件自动添加约束,而Inference
会给当前界面中的所有元素自动添加约束。可以一键自动生成所有控件的约束,如下图所示
删除约束
控件分别有四个方向上的约束点,四个角的正方形图标拖动可以改变控件的大小。要删除约束也很简单,选中控件后点击坐下角的图标就删除了当前控件的所以约束,点击某一个约束的原点可以删除单个约束
当然你也可以点击工具栏的上如下图的图标,那么会清除布局中所有的约束
Properties属性栏
当我们选中某个控件后那么视图的右边则是当前控件可以设置的属性栏。一些基本的属性设置这里就不讲解了,主要了解下如图所示的区域如何使用,这部分也叫Inspector
这部分就是来控制控件的宽高以及Margins
值。
相对约束定位控件
当一个控件上有至少两个对立的连接时, 比如上和下, 或者左和右, 你可以看到一个可以让你沿着对立连接的轴调整控件位置的滑块. 这也被称为横向或纵向偏量. 如下图
拖动滑块可以改变控件的横向或者或者纵向的偏移量. 另外也可以通过移动控件到目标目标位置实现这一点。
控件宽高尺寸
空间的宽高可以通过单击下图中的线来控制控件宽高
宽高有以下选项
-
Fixed
: 此选项允许你指定控件的高和宽.
-
AnySize
: 此选项让控件占用所有可用空间以适应约束. 换句话说, 这更像是匹配约束. 与match_parent
不同, 后者占用父 View 的所有可用空间.
-
Wrap Content
: 这个就是以前XML布局的Wrap Content
是相同的
注意AnySize
和 match_parent
有所不同,如果 左边的ImageView
约束于右边的 Button
, 设置为AnySize
只会扩展它适应 右边的button
,通过下面这张图应该就很好理解了。
点击外围的线可以调整控件的Margins
值。
Guidelines
Guidelines
可以帮助你在添加约束布局的时候更方便的确定控件的位置,可以创建垂直或者水平方向的Guidelines
,创建后可以点击选择Guidelines
位置的方式,默认是距离左边多少dp,点击后可以切位为距离右边的距离和屏幕的百分比距离
如果我们要两个按钮水平居中就需要用到Guidelines
可以看到我们给左边的按钮添加了约束,距离底部
24dp
右边约束于Guidelines
,右边的按钮则左边约束于Guidelines
而顶部则于左边按钮对齐,这样两个按钮就水平居中对齐了。
链条布局 Chains
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 写界面方式啊,更简便更高效!