ConstraintLayout详解

回忆当初稍微复杂的界面,布局的层级嵌套多层,布局最终会解析成 View 的树形结构,这对渲染性能产生了一定的影响,并且也增大了代码的维护难度。Google 工程师正是考虑到这一因素,推出了 ConstraintLayout!!不得不说,真特么好用。。。

ConstraintLayout翻译为约束布局,也有人把它称作增强型的相对布局,由 2016 年 Google I/O 推出。扁平式的布局方式,无任何嵌套,减少布局的层级,优化渲染性能。从支持力度而言,将成为主流布局样式,完全代替其他布局。有个成语用的非常好,集万千宠爱于一身,用到这里非常合适,约束集 LinearLayout(线性布局),RelativeLayout(相对布局),百分比布局等的功能于一身,功能强大,使用灵活。纸上得来终觉浅,绝知此事要躬行。让我们在实际开发的场景中去检验约束布局,在实战中积累经验。

接下来我会以实际开发中遇到的几个场景来讲解。

题外话,本文需要您对 ConstraintLayout  有一定的熟悉了解度,若您对 ConstraintLayout 不熟悉请链接一下地址:

ConstraintLayout 官方文档

为了要使用ConstraintLayout,我们需要在app/build.gradle文件中添加ConstraintLayout的依赖,如下所示。

dependencies {

    compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'

}

ConstraintLayout常用属性:

layout_constraintTop_toTopOf— 期望视图的上边对齐另一个视图的上边

layout_constraintTop_toBottomOf— 期望视图的上边对齐另一个视图的底边

layout_constraintTop_toLeftOf— 期望视图的上边对齐另一个视图的左边

layout_constraintTop_toRightOf— 期望视图的上边对齐另一个视图的右边

layout_constraintBottom_toTopOf— 期望视图的下边对齐另一个视图的上边

layout_constraintBottom_toBottomOf— 期望视图的底边对齐另一个视图的底边

layout_constraintBottom_toLeftOf— 期望视图的底边对齐另一个视图的左边

layout_constraintBottom_toRightOf— 期望视图的底边对齐另一个视图的右边

layout_constraintLeft_toTopOf— 期望视图的左边对齐另一个视图的上边

layout_constraintLeft_toBottomOf— 期望视图的左边对齐另一个视图的底边

layout_constraintLeft_toLeftOf— 期望视图的左边对齐另一个视图的左边

layout_constraintLeft_toRightOf— 期望视图的左边对齐另一个视图的右边

layout_constraintRight_toTopOf— 期望视图的右边对齐另一个视图的上边

layout_constraintRight_toBottomOf— 期望视图的右边对齐另一个视图的底边

layout_constraintRight_toLeftOf— 期望视图的右边对齐另一个视图的左边

layout_constraintRight_toRightOf— 期望视图的右边对齐另一个视图的右边

1、Circular positioning(圆形定位)

标题后面的中文是自己翻译的,可能不是很准确。

官方文档是这么介绍的:

You can constrain a widget center relative to another widget center, at an angleanda distance. This allows you to position a widget on a circle

我是这么理解的,您可以将一个控件的中心以一定的角度和距离约束到另一个控件的中心,相当于在一个圆上放置一个控件。

示例代码如下:

 

效果图:

c_1

图文并茂,理解起来较容易些。圆形定位使用其他布局是很难实现的(除自定义外),该功能在实际的开发中用的并不多,可以用来实现类似钟表的效果。该功能只不过是约束布局的冰山一角,且往下看。2、WRAP_CONTENT : enforcing constraints(强制约束)

官方文档是这么介绍的:

If a dimensionisset to WRAP_CONTENT,inversions before1.1they will be treatedasa literal dimension -- meaning, constraints willnotlimit the resulting dimension. Whileingeneral thisisenough (andfaster),insome situations, you might want to use WRAP_CONTENT, yet keep enforcing constraints to limit the resulting dimension. In that case, you can add one of the corresponding attribute

英文一直是我的弱项,我是这么理解的,1.1.0 版本之前是没有这个功能的,说的是控件的宽设置为WRAP_CONTENT(包裹内容)时,如果实际宽度超过了约束的最大宽度,那么约束会失效(高同理),为了防止约束失效,增加了以下属性:

app:layout_constrainedWidth=”true|false”    //默认false

app:layout_constrainedHeight=”true|false”    //默认false

官网并没有过多说明,那么怎么去理解呢,接下来以app:layout_constrainedWidth属性来看两个例子。

a、例子

c_2

B控件位于A控件右侧与屏幕右侧的中间。代码如下:

   

那么我改变B控件的内容,使宽度增大:

c_3

通过效果图可以得出,给B控件添加的左右约束失效。为了防止约束失效,在1.1.0版本中新增了app:layout_constrainedWidth="true"属性。注意控件的左右都应该有约束条件, 如下:

app:layout_constraintLeft_toRightOf="@+id/bt_1"//控件的左边位于xx控件的右边app:layout_constraintRight_toRightOf="parent"//控件的右边位于xx控件的右边

效果图如下:

c_4

app:layout_constrainedWidth="true" 会导致渲染变慢,变慢时长可忽略不计。

3、MATCH_CONSTRAINT dimensions(填充父窗体约束)

官方文档是这么介绍的:

When a dimension issetto MATCH_CONSTRAINT, thedefaultbehavior is to have the resulting size take all the available space. Several additional modifiers are available

在约束布局中宽高的维度match_parent被0dp代替,默认生成的大小占所有的可用空间。那么有以下几个属性可以使用:

layout_constraintWidth_min and layout_constraintHeight_min  //设置最小尺寸

layout_constraintWidth_max and layout_constraintHeight_max  //设置最大尺寸

layout_constraintWidth_percent and layout_constraintHeight_percent  //设置相对于父类的百分比

开发中有这样一个需求,位于父控件的中间且宽度为父控件的一半,那么我们可以这么去实现:

c_6

4、goneMargin(隐藏边距)

当约束目标的可见性为View.GONE时,还可以通过以下属性设置不同的边距值:

layout_goneMarginStart

layout_goneMarginEnd

layout_goneMarginLeft

layout_goneMarginTop

layout_goneMarginRight

layout_goneMarginBottom

如以下例子:

c_16

Margins and chains (in 1.1)Optimizer (in 1.1)略。

5、约束之百分比布局

百分比布局大家肯定不会陌生,由于Android的碎片化非常严重,那么屏幕适配将是一件非常令人头疼的事情,百分比适配也就应运而生,约束布局同样也可以实现百分比的功能,并且更加强大,灵活。

经常我们会遇到这样的需求,个人主页要求顶部的背景图宽高16:9来适配,如下图:

c_7

约束布局的实现方式如下:

<!-- "W,9:16" 同样的效果 -->

新增了如下属性:

app:layout_constraintDimensionRatio="H,16:9"

官网的介绍是这样的:

You can also define one dimension of a widget as a ratio of the other one. In order todothat, you need to have at least one constrained dimension besetto0dp (i.e., MATCH_CONSTRAINT),andsetthe attribute layout_constraintDimensionRatio to a given ratio

意思是说约束布局支持子控件设置宽高比,前提条件是至少需要将宽高中的一个设置为0dp。为了约束一个特定的边,基于另一个边的尺寸,可以预先附加W,或H以逗号隔开。

然后需求变动,需要将宽度调整为屏幕的一半:

c_8

只需要新增app:layout_constraintWidth_percent="0.5"属性。

接着需要控件左对齐:

c_9

同时新增了app:layout_constraintHorizontal_bias="0"属性。

官网的介绍如下:

Thedefaultwhen encountering such opposite constraints is to center the widget; but you can tweak the positioning to favor one side over anotherusingthe bias attributes:

具有相反方向约束的控件,我们可以改变偏好值,来调整位置偏向某一边。有点类似LinearLayout的weight属性。

最后需要调整控件距离顶部的高度为父控件高度的20%:

c_10

这里用到了虚拟辅助类Guideline,同时1.1.0版本还添加了两个虚拟类Barrier,Group。它们是虚拟对象,并不会占用实际的空间,但可以帮助我们更好更精细地控制布局。综上的需求变化我们可以相对于父控件任意改变控件大小,控件的位置,从而能够更好的适配各大屏幕。

5、Guideline

Guideline 与 LinearLayout 类似可以设置水平或垂直方向,android:orientation="horizontal",android:orientation="vertical",水平方向高度为0,垂直方向宽度为0。Guideline 具有以下的三种定位方式:

layout_constraintGuide_begin  距离父容器起始位置的距离(左侧或顶部)

layout_constraintGuide_end    距离父容器结束位置的距离(右侧或底部)

layout_constraintGuide_percent    距离父容器宽度或高度的百分比

例如,设置一条垂直方向距离父控件左侧为100dp的Guideline:

效果图如下:

c_17

6、Barrier

Barrier,直译为障碍、屏障。在约束布局中,可以使用属性constraint_referenced_ids属性来引用多个带约束的组件,从而将它们看作一个整体,Barrier 的介入可以完成很多其他布局不能完成的功能,如下:

开发中有这样的一个需求,看下图:

c_11

姓名,联系方式位于 A 区域(随着文本的宽度变化 A 区域的宽度也随之变化),B 区域在 A 区域的右侧。使用传统的布局方式实现嵌套过多,布局不够优雅。那么我们一起来看看约束布局是怎么去实现的:

               

barrierDirection指定方向,constraint_referenced_ids引用的控件 id(多个id以逗号隔开)。

7、Group

Group用于控制多个控件的可见性。

e.g:

c_12

若android:visibility="gone"那么 A,B 控件都会隐藏。

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

推荐阅读更多精彩内容