ConstraintLayout的使用

?? ConstraintLayout布局出现已经很长一段时间了,一直不习惯用。但是使用传统的布局实在太麻烦了,就仔细研究了下ConstraintLayout的官方文档,学习一下ConstraintLayout的使用。简单总结成一篇文章(其实就是翻译官方文档的内容),分享给大家仅供参考学习。

ConstraintLayout的官方文档

1、介绍

?? ConstraintLayout是一种约束布局,继承自ViewGroup??梢栽贏pi>=9的Android系统上使用。它以灵活的方式定位和调整控件的方法解决了布局嵌套过多的问题。

?? 下面介绍下ConstraintLayout的约束类型

2、相对布局

?? 相对定位是在ConstraintLayout中创建的布局的基本构建块之一。这些约束运行你给定的控件相对另一个控件进行定位。约束方向有垂直和水平两个方向。

  • 水平轴:左、右、起点和终点
  • 垂直轴:顶部、底部和文本基线

?? 一般概念是将窗口小部件的给定侧约束到任何其他窗口小部件的另一侧。例如,为了将按钮B定位在按钮A的右侧(图1):

代码里需要这样写:

<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
        app:layout_constraintLeft_toRightOf="@+id/buttonA" />

?? 这告诉系统我们希望按钮B的左侧被约束到按钮A的右侧。这样的位置约束意味着系统将尝试让双方共享相同的位置。

以下是可用约束的列表(图2):

  • layout_constraintLeft_toLeftOf
  • layout_constraintLeft_toRightOf
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintBaseline_toBaselineOf
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

它们都引用id另一个小部件,或者parent引用父容器,即ConstraintLayout:

<Button android:id="@+id/buttonB" ...
        app:layout_constraintLeft_toLeftOf="parent" />

3、边距

?? 如果设置了边距,则它们将应用于相应的约束(如果存在)(图3),将边距强制为目标和源边之间的空间。通常的布局边距属性可用于此效果:

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginLeft
  • android:layout_marginTop
  • android:layout_marginRight
  • android:layout_marginBottom

这里请注意,边距值只能是正数或等于零。

连接到隐藏的控件时的边距
当位置约束目标的可见性为View.GONE,您还可以使用以下属性指示要使用的不同边距值:

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

4、居中定位和偏移

?? 一个有用的方面ConstraintLayout是它如何处理“不可能”的约束。例如,如果我们有类似的东西:

<android.support.constraint.ConstraintLayout ...>
      <Button android:id="@+id/button" ...
              app:layout_constraintLeft_toLeftOf="parent"
              app:layout_constraintRight_toRightOf="parent/>

</android.support.constraint.ConstraintLayout>

?? 除非ConstraintLayout恰好具有Button与之完全相同的大小,否则两个约束不能同时满足(双方都不能在我们希望它们的位置)。

?? 在这种情况下发生的事情是,约束的作用就像是相反的力量将小部件拉平(图4); 这样小部件最终将在父容器中居中。这同样适用于垂直约束。

偏移
?? 遇到这种相反的约束时的默认设置是使窗口小部件居中; 但是您可以使用偏差属性调整定位以支持一侧而不是另一侧:

  • layout_constraintHorizontal_bias
  • layout_constraintVertical_bias

例如,以下将使左侧具有30%的偏差而不是默认的50%,使得左侧将更短,小部件更倾向于左侧(图5)

<android.support.constraint.ConstraintLayout ...>
         <Button android:id="@+id/button" ...
                 app:layout_constraintHorizontal_bias="0.3"
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent/>
</>

使用偏差,您可以制作更好地适应屏幕尺寸变化的用户界面。

5、圆心定位

?? 您可以以角度和距离约束窗口小部件中心相对于另一个窗口小部件中心。这允许您将小部件放在圆上(参见图6)??梢允褂靡韵率粜裕?/p>

  • layout_constraintCircle :引用另一个小部件ID
  • layout_constraintCircleRadius :到其他窗口小部件中心的距离
  • layout_constraintCircleAngle :小部件应该处于哪个角度(以度为单位,从0到360)

代码可以这样写:

<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
      app:layout_constraintCircle="@+id/buttonA"
      app:layout_constraintCircleRadius="100dp"
      app:layout_constraintCircleAngle="45" />

6、可见性行为

?? ConstraintLayout具有标记为小部件的特定处理View.GONE。属性值View.GONE像往常一样,控件不会显示,也不是布局本身的一部分(例如,如果标记为实际尺寸,则不会更改它们GONE)。

但就布局计算而言,GONE小部件仍然是其中的一部分,具有重要的区别:

  • 对于布局传递,它们的尺寸将被视为零(基本上,它们将被解析为一个点)
  • 如果他们对其他小部件有限制,他们仍然会受到尊重,但任何边距都会好像等于零

?? 注意:使用的边距将是B在连接到A时定义的边距(例如,参见图7)。在某些情况下,这可能不是您想要的余量(例如A在其容器侧面有100dp的边距,B只有16dp到A,A标记为已消失,B将有16dp的余量到容器)。因此,您可以指定在连接到标记为已消失的窗口小部件时要使用的备用边距值(请参阅上面有关已删除边距属性的部分)。

7、尺寸限制

ConstraintLayout的尺寸设置有:

  • android:minWidth 设置布局的最小宽度
  • android:minHeight 设置布局的最小高度
  • android:maxWidth 设置布局的最大宽度
  • android:maxHeight 设置布局的最大高度
    ConstraintLayout当尺寸设置 为时,将使用这些最小和最大尺寸WRAP_CONTENT。

小部件维度约束
可以通过以3种不同方式设置android:layout_width和 android:layout_height属性来指定小部件的维度:

  • 使用特定维度(文字值,例如123dp或Dimension参考)
  • 使用WRAP_CONTENT,这将要求小部件计算自己的大小
  • 使用0dp,相当于“ MATCH_CONSTRAINT”

前两个以与其他布局类似的方式工作。最后一个将以匹配所设置的约束的方式调整窗口小部件的大小(参见图8,(a)是wrap_content,(b)是0dp)。如果设置了边距,则在计算中将考虑它们(图8,(c)中的0dp)。

重要提示: MATCH_PARENT不建议用于a中包含的小部件ConstraintLayout??梢酝ü褂肕ATCH_CONSTRAINT设置为相应的左/右或上/下约束来定义类似的行为"parent"。

WRAP_CONTENT:强制约束(在1.1中添加)

?? 如果将维度设置为WRAP_CONTENT,则在1.1之前的版本中,它们将被视为文字维度 - 这意味着约束不会限制生成的维度。虽然通常这足够(并且更快),但在某些情况下,您可能希望使用WRAP_CONTENT,但仍然强制执行约束以限制结果维度。在这种情况下,您可以添加一个相应的属性:

  • app:layout_constrainedWidth=”true|false”
  • app:layout_constrainedHeight=”true|false”

MATCH_CONSTRAINT尺寸(1.1中添加)

?? 当维度设置为时MATCH_CONSTRAINT,默认行为是使结果大小占用所有可用空间?;褂屑父龆钔獾男奘畏?/p>

  • layout_constraintWidth_min和layout_constraintHeight_min:将设置此维度的最小大小
  • layout_constraintWidth_max和layout_constraintHeight_max:将设置此维度的最大大小
  • layout_constraintWidth_percent和layout_constraintHeight_percent:将此维度的大小设置为父级的百分比

最小和最大

?? 为min和max指示的值可以是Dp中的维度,也可以是“wrap”,它将使用与其相同的值WRAP_CONTENT。

百分比

要使用百分比,您需要设置以下内容:

  • 尺寸应设置为MATCH_CONSTRAINT(0dp)
  • 默认值应设置为百分比
    app:layout_constraintWidth_default="percent" 或app:layout_constraintHeight_default="percent"
  • 然后将layout_constraintWidth_percent 或layout_constraintHeight_percent属性设置为0到1之间的值

比率

?? 您还可以将窗口小部件的一个维度定义为另一个维度的比率。为此,您需要将至少一个约束维度设置为0dp(即MATCH_CONSTRAINT),并将该属性layout_constraintDimensionRatio设置为给定比率。例如:

<Button android:layout_width="wrap_content"
      android:layout_height="0dp"
      app:layout_constraintDimensionRatio="1:1" />

将按钮的高度设置为与其宽度相同。该比率可表示为:

  • 浮点值,表示宽度和高度之间的比率
  • “宽度:高度”形式的比率

?? 如果两个尺寸都设置为MATCH_CONSTRAINT(0dp),您也可以使用比率。在这种情况下,系统设置满足所有约束的最大尺寸并保持指定的纵横比。要根据另一个特定边的尺寸约束一个特定边,可以预先附加W,“或” H,分别约束宽度或高度。例如,如果一个尺寸受两个目标约束(例如,宽度为0dp并且以父节点为中心),则可以指示应该约束哪一边,通过 在比率前添加字母W(用于约束宽度)或H(用于约束高度),用逗号分隔:

 <Button android:layout_width="0dp"
       android:layout_height="0dp"
       app:layout_constraintDimensionRatio="H,16:9"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintTop_toTopOf="parent"/>

将按照16:9的比例设置按钮的高度,而按钮的宽度将匹配父项的约束。

8、链

?? 链在单个轴(水平或垂直)中提供类似行的行为。另一个轴可以独立约束。

创建一个链
?? 如果一组小部件通过双向连接链接在一起,则它们被视为链(参见图9,显示最小链,具有两个小部件)。

链头
?? 链由链的第一个元素(链的“头部”)上设置的属性控制:

头部是水平链的最左侧小部件,垂直链的最顶部小部件。

链中的边距
??如果在连接上指定了边距,则会考虑它们。在扩散链的情况下,将从分配的空间中扣除边距值。

链式
?? 设置属性layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle链的第一个元素时,链的行为将根据指定的样式(默认值CHAIN_SPREAD)更改。

  • CHAIN_SPREAD - 元素将展开(默认样式)
  • 加权链入CHAIN_SPREAD模式,如果设置了一些小部件MATCH_CONSTRAINT,它们将分割可用空间
  • CHAIN_SPREAD_INSIDE - 类似,但链的端点不会散开
  • CHAIN_PACKED - 链条的元素将被包装在一起。然后,子项的水平或垂直偏差属性将影响打包元素的定位

加权链

?? 链的默认行为是在可用空间中平均分布元素。如果使用了一个或多个元素MATCH_CONSTRAINT,它们将使用可用的空白空间(在它们之间平均分配)。属性layout_constraintHorizontal_weight和layout_constraintVertical_weight 将控制如何将空间利用的元素之间进行分配MATCH_CONSTRAINT。例如,在包含两个元素的链上使用MATCH_CONSTRAINT,第一个元素使用权重2,第二个元素使用权重1,第一个元素占用的空间将是第二个元素占用的空间的两倍。

边距和链条(1.1)

?? 在链中的元素上使用边距时,边距是相加的。
例如,在水平链上,如果一个元素定义了10dp的右边距,而下一个元素定义了5dp的左边距,则这两个元素之间产生的边距为15dp。
在计算链用于定位项目的剩余空间时,会同时考虑项目及其边距。剩余空间不包含边距。

9、虚拟助手对象

?? 除了之前详述的内在功能外,您还可以使用特殊的辅助对象ConstraintLayout来帮助您进行布局。目前,该Guideline对象允许您创建相对于ConstraintLayout容器定位的水平和垂直准线。然后可以通过将小部件限制为这样的指导来定位小部件。在1.1中,Barrier也Group被添加了。

10、优化

?? 在1.1中我们公开了约束优化器。您可以通过将标记app:layout_optimizationLevel添加到ConstraintLayout元素来决定应用哪些优化。

  • none:不应用任何优化
  • 标准:默认。仅优化直接和屏障约束
  • 直接:优化直接约束
  • 障碍:优化障碍限制
  • 链:优化链约束(实验)
  • 维度:优化维度度量(实验),减少匹配约束元素的度量数量
    此属性是一个掩码,因此您可以通过列出所需的优化来决定打开或关闭特定的优化。例如:app:layout_optimizationLevel =“direct | barrier | chain”
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容