转载地址:http://blog.csdn.net/qiujuer/article/details/51462471
序
在Google IO大会中不仅仅带来了Android Studio 2.2预览版,同时带给我们一个依赖约束的库。
简单来说,她是相对布局的升级版本,但是区别与相对布局更加强调约束。何为约束,即控件之间的关系。
她能让你的布局更加扁平化,一般来说一个界面一层就够了;同时借助于AS我们能极其简单的完成界面布局。
准备
1.准备好Android Studio 2.2预览版,在这里给大家准备好了下载链接:
为什么需要预览版,其实就库来说并不需要AS最新版本,但是这样我们只能使用代码来进行布局,而ConstraintLayout让布局回归原始,拖动即可。比起常规控件拖动基本是分分钟高潮的节奏。
2.首先在项目中添加依赖:
<code class="hljs matlab has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">dependencies <span class="hljs-cell" style="box-sizing: border-box;">{
compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.android.support.constraint:constraint-layout:1.0.0-alpha1'</span>
}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
注意:正式版本还未发布。
初尝禁果
首先我们建立 activity_start.xml 布局,并添加如下代码:
<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-pi" style="color: rgb(0, 102, 102); box-sizing: border-box;"><?xml version="1.0" encoding="utf-8"?></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">android.support.constraint.ConstraintLayout</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">xmlns:android</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"http://schemas.android.com/apk/res/android"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">xmlns:app</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"http://schemas.android.com/apk/res-auto"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:id</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@+id/lay_root"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:layout_width</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"match_parent"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:layout_height</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"match_parent"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">ImageView
</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:id</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@+id/iv_head"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:layout_width</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wrap_content"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:layout_height</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wrap_content"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:src</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@drawable/dog"</span> /></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">android.support.constraint.ConstraintLayout</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
在这个代码中我们定义了根布局为ConstraintLayout,然后添加了一个ImageView。请注意在代码中尽量为每一个控件都加上id名称,因为约束布局需要知道每一个控件之间的关系。
要让图片布局水平居中哪么我们更改ImageView部分代码为:
<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">ImageView
</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:id</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@+id/iv_head"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:layout_width</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wrap_content"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:layout_height</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wrap_content"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:src</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@drawable/dog"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">app:layout_constraintLeft_toLeftOf</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@+id/lay_root"</span>
<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">app:layout_constraintRight_toRightOf</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@+id/lay_root"</span> /></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
如果要垂直居中,哪么我们继续添加代码:
<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <ImageView
android:id=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@+</span>id/iv_head"</span>
android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span>
android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span>
android:src=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@drawable</span>/dog"</span>
app:layout_constraintBottom_toBottomOf=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@id</span>/lay_root"</span>
app:layout_constraintLeft_toLeftOf=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@+</span>id/lay_root"</span>
app:layout_constraintRight_toRightOf=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@+</span>id/lay_root"</span>
app:layout_constraintTop_toTopOf=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@id</span>/lay_root"</span> /></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
此时我们的控件已经居中在最中央了。
当然为了证明水平居中,我们限定图片宽度为100dp:
![这里写图片描述](https://img-blog.csdn.net/20160520160718654)
工作区
我们先来看看 Android Studio 2.2 Preview1 提供的工作区。
![这里写图片描述](https://img-blog.csdn.net/20160520160705904)
在工作区中有两种预览,一种设计预览,一种叫做蓝图的东西。两者可以辅助进行布局预览,非常Nice。
眼睛图标:用来控制是否显示约束的东西。
磁铁图标:用来自动吸附的东西,就是说两个按钮放在一起的时候会自动按照一定的约束条件进行链接。
清理图标:用来清除所有的约束,当鼠标放倒一个控件上时也会有一个清理图标出现,点击可以清除当前选中的控件的约束。
灯泡图标:用来自动推断约束条件的东西,运用这个可以更加智能快速的完成布局。
基础
在布局引擎中,能为你的控件手动或者自动的创建一定的布局约束;为了更好的理解约束,下面来看一些案例(源于谷歌案例)。
约束
简单来说约束可以帮助你按照某种相互关系进行布局,可以让控件对齐等等操作,在这里我们操作后面的按钮并链接到前一个按钮的右端,并且间隔56dp。哪么此时无论我移动按钮1到哪儿,按钮2都将在按钮1的右边并间距56dp。
![这里写图片描述](https://img-blog.csdn.net/20160520161231449)
手柄类型
在这个图中我们看见有3种不同的手柄。
调整手柄
![这里写图片描述](https://img-blog.csdn.net/20160520161247981)
拖动该手柄能帮助你调整整个控件的大小。
约束手柄
![这里写图片描述](https://img-blog.csdn.net/20160520161300356)
这个约束手柄位于控件的四边,在四边上有四个小圆点,拖动该圆点并指向另外的控件的一边,哪么可以让该控件对其到指向的控件。
当然你可以设置margin来提供对应的间距。如果需要清理掉单个约束,点击该圆点即可。
手柄限制:
- 左右两边的手柄只能链接到另外一个控件的左右两边,上下手柄同样。
基线手柄
![这里写图片描述](https://img-blog.csdn.net/20160520161351154)
该手柄仅仅出现在有文字的控件中使用,或者继承TextView的控件中使用,其作用是对齐两个控件的文字基线。
基线限制:
- 基线只能链接到另一个控件的基线。
- 基线也不能与手柄进行链接。
谷歌的案例
1.首先选择一个约束手柄,并按住鼠标拖动到另外一个控件的手柄原点上,当链接线变成绿色的时候松开鼠标即可创建一个约束。
![这里写图片描述](https://img-blog.csdn.net/20160520161629408)
2.添加图片控件,链接TextView控件的顶部手柄到ImageView底部手柄,并拖动一定间距。可以看出约束添加时文本控件自动吸附到了图片的底部。
![这里写图片描述](https://img-blog.csdn.net/20160520163111068)
3.拖动图片控件顶部手柄到根布局顶部。
![这里写图片描述](https://img-blog.csdn.net/20160520163415009)
4.最后我们同时添加图片左边与右边的约束使其居中对齐。
![这里写图片描述](https://img-blog.csdn.net/20160520163521058)
5.添加基线约束。
![这里写图片描述](https://img-blog.csdn.net/20160520163636762)
是不是很简单?从未感觉布局如此简单,如果使用传统布局进行拖动必定不能做到多屏幕适配的问题,而约束布局却不会,约束强调相互关系,并不固定位置。
属性面板
上面的是一些基本用法,下面来看看属性面板。在这里将学到更加Nice的自定义化设置。
首先我们在屏幕上添加一个图片控件,并添加四边约束到根布局,此时我们看见的界面是这样的:
![这里写图片描述](https://img-blog.csdn.net/20160520164200294)
在属性面板的上面部分是我们的检查员(Inspector),在这个视图中显示了当前选中的控件的约束情况。
-
Margins:间距,在这个面板中我们可以看见当前图片控件相对约束的控件来说四边都具有16dp的间距。
-
删除约束:鼠标放到检查器上中间正方形边上会出现一个删除按钮,点击此按钮即可删除当前方向的约束。
-
百分比定位:当你同时创建了左右两边的约束的时候,你会在监视器上看见一个水瓶的进度条,默认情况是50的值,意味着相对你的左右两边的控件约束进行居中对齐。你可以拖动这个进度条进行更改;同理上下同时创建约束后也将有一个垂直方向的进度条出现。
![这里写图片描述](https://img-blog.csdn.net/20160520165235409)
-
控件自身尺寸:对于控件自身的大小控制有3种不同的类型,你可以通过点击中间正方形上的线来进行切换。
Fixed: 该模式下为固定尺寸,你可以设置控件的width/height属性来控制高和宽。
AnySize: 该模式可以让控件占据所有可用的空间来满足约束。换句话说,这更像是匹配约束。不同于match_parent,是占据父视图的所有可用空间;AnySize模式下是满足约束的情况下尽量满足控件的大小空间。
Wrap Content: 在该模式下,控件所占有的空间是可缩放的,相当于“wrap_content“属性。
我们来看一个从Fixed模式调整为AnySize模式的对比图:
调整图片的宽度占有属性为AnySize模式之后:
![这里写图片描述](https://img-blog.csdn.net/20160520170357784)
到这里基本是使用是OK了,下面再说两点额外的操作。
更多
自动链接
还记得上面说到工作区的时候说的自动链接磁铁图标么?
首先我们启用该功能。然后新建界面并且拖动一个图片控件到中心部分,然后放开,此时会看见编辑器自动为我们添加了图片四边的约束。
![这里写图片描述](https://img-blog.csdn.net/20160520171533127)
自动推断
自动推断也是用来辅助用户创建控件约束的;其原理是综合控件之间的关系创建对应的约束条件。
与自动链接的区别:
自动链接,自动推断都是辅助创建约束。但是自动链接是在用户拖动一个控件后为当前拖动的控件创建约束;而自动推断不同,自动推断会综合考虑全部控件之间的关系,然后根据布局创建控件之间的相互约束关系。
要测试自动推断,首先我们关闭自动链接功能,此时我们添加一些控件,控件的布局如下,因为我们关闭了自动链接,并且采用拖动关系进行创建,此时界面上控件之间是没有约束关系的。
此时我们在手机上看见的是这样:
全部被挤压到了一块儿。
此时我们点击顶部的
图标,自动推断约束,然后可以看见我们的布局变了:
此时再看看我们的手机上的效果:
Very Nice~~
总结
在本篇文章中仅仅只是说明了约束布局的操作,详细的约束布局创建的XML内容以及原理并没有在这一章中进行讲解,会在后续章节中讲解;当然说到布局XML,在约束布局中并不建议直接操作XML文件来完成布局,而建议使用鼠标拖动来添加对应的约束。
通过本篇文章的学习,基本上一个简单的不需要滚动的布局都可以使用约束布局来完成,也仅仅只需要一层就可以了,所有的控件无论在多一层足够了。
这是否意味着抛弃其他控件?并不是的!约束布局仅仅只是一种新的思路,其适用于界面不太复杂,并且不滚动的界面中布局,如果界面元素很多甚至超过屏幕,哪么并不建议使用约束布局。
另外约束布局仅仅是简单快捷的布局,其性能负担随着界面中的控件数量以及约束条件的增加而增加;所以使用时还需要多多考究。
文章的末尾处附上一份谷歌的案例效果:
![这里写图片描述](https://img-blog.csdn.net/20160520175022478)
文章中的项目托管到Github:
https://github.com/qiujuer/BeFoot/tree/master/blog/sample/ConstraintLayout
另外:还有两篇国外的地址
http://riggaroo.co.za/constraintlayout-101-new-layout-builder-android-studio/
http://medium.com/exploring-android/exploring-the-new-android-constraintlayout-eed37fe8d8f1