ConstraintLayout的使用

ConstraintLayout的使用

这篇文章主要根据官方文档的结构,加上自己的理解来介绍它的用法。
ConstraintLayout 翻译过来是约束布局,可以对子view添加各种约束条件达到某种目的,非常灵活。
ConstraintLayout是一个ViewGroup的导出类,可以用灵活的方式来放置部件和确定部件大小。

引入依赖

开始使用ConstraintLayout前,需要在工程引入ConstraintLayout依赖库。
添加以下依赖到你的build.gradle 文件中:

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
}

开发指南

主要通过以下几个方面来介绍ConstraintLayout的使用和特性:

  • 相对定位
  • 边距
  • 居中和偏移
  • 圆形定位
  • 可见度的行为
  • 部件尺寸的约束
  • 比例
  • 链条

相对定位

相对定位跟RelativeLayout非常像,一个部件相对另外一个部件的位置。如把ButtonB放到ButtonA的右边,可以这样写:

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

Fig. 1 - Relative Positioning Example

有以下可用的约束属性:

  • 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

Fig. 2 - Relative Positioning Constraints

这些属性都是可以引用另外一个部件的id,或者parent(指的是引用父容器,实际指的是ConstraintLayout)

外边距

Fig. 3 - Relative Positioning Margins

如果设置了margins,它会运用于相应的约束(如果存在的话),强制将margins当做一个空间在目标的边和原始的边之间,有以下有效的属性:

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

注意这些属性的值只能是正数或者0

当连接了GONE的部件时的边距

如果约束目标的部件为GONE时,可以设置以下属性来设置边距,只在目标GONE时有效.

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

注意目标为GONE时同时设置了layout_goneMarginStart和layout_marginStart,只有layout_goneMarginStart会有效

居中和偏移

看个例子

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

Fig. 4 - Centering Positioning

这个例子控件添加了左边跟父容器对齐,右边也跟父容器对齐的约束。看是不可能发生,除非子控件的宽跟父容器一致。
实际上如果这样这种对立面的约束(横向或者竖向)会导致部件刚好居中,可以想象成两个相反方向的力度拉伸,力是相等的,可以类比拔河,双方的力一样,刚好居中。

偏移

对立面的约束默认是居中,可以通过设置以下两个属性进行偏向一边
* layout_constraintHorizontal_bias
* layout_constraintVertical_bias

Fig. 5 - Centering Positioning with Bias

值为0到1,如果是0.5,部件刚好居中
使用偏移,可以放置部件到自己想要的位置

例如把一个按钮放到水平的30%的位置,默认是50%。

<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/>
    </>

圆形定位(1.1新增)

你可以通过一个部件的中心约束另外一个部件的中心,通过角度,距离。这使得你定位部件在一个圆上。对应的属性有:

  • layout_constraintCircle : 引用另外一个部件的id
  • layout_constraintCircleRadius : 到另一个部件中心点的距离,实际就是半径
  • layout_constraintCircleAngle : 角度 (0 to 360)

Fig. 6 - Circular Positioning
Fig. 6 - Circular Positioning

例如: ButtonB 位于 ButtonA中心点的45度,中心点距离为100dp

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

可见度的行为

ConstraintLayout有特殊处理被标记为GONE的部件(layout_goneMargin).
GONE的部件,通常不显示和不是layout一部分(实际上他们的dimension不改变当标记为GONE时 )
但是根据layout的计算,GONE仍然是它的一部分,有重大的区别:
对于布局的传递,他们的dimension认为是0(基本上他们可以当做一个点来看待)
如果他们约束了其他部件,它的所有margins当做为0
这种行为允许构建你能暂时标记GONE的部件的布局,而不是破坏布局。当做一些简单的动画时特别有用

Fig. 7 - Visibility Behavior

尺寸的约束

  • android:minWidth 设置最小的宽度
  • android:minHeight 设置最小的高度
  • android:maxWidth 设置最大的宽度
  • android:maxHeight 设置最大的高度

这些值用在ConstraintLayout,当他们的dimensions设置成WRAP_CONTENT的时候

部件尺寸的约束

部件的尺寸是通过设置android:layout_widthandroid:layout_height属性指定的,有3种方式:
* 使用一个明确的尺寸值(字面值如123dp或者值引用)
* 使用WRAP_CONTENT,请求部件计算自己的值
* 使用0dp,等价于MATCH_CONSTRAINT,类似于其他layout的match_parent,在约束条件下可以用的最大的值

Fig. 8 - Dimension Constraints70)

前两种跟其他的布局类似。最后一种会重新计算部件通过适配设置的约束。如果边距有设置,计算时也会考虑边距。

重要提醒:ConstraintLayout不推荐包含MATCH_PARENT的部件。类似行为可以使用MATCH_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,默认行为的结果大小为是用所有可用的空间,有以下几个额外修改的属性:

  • layout_constraintWidth_min and layout_constraintHeight_min : 设置最小的大小
  • layout_constraintWidth_max and layout_constraintHeight_max : 设置最大的大小
    layout_constraintWidth_percent and layout_constraintHeight_percent : 设置大小根据百分比

值可以是dp的字面值或者wrap,如果是wrap表示跟WRAP_CONTENT一样

百分比大小

使用百分比,需要设置下列事物:
* 尺寸需要设置成MATCH_CONSTRAINT (0dp)
* 这两个属性要设置成percent app:layout_constraintWidth_default=”percent” or app:layout_constraintHeight_default=”percent” (1.1之后不需要)
* 设置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" /> 

这个例子将设置高和宽一样
比例可以这样表达:
* 一个浮点数,代表宽高之间的比例
* 比例的格式”width:height”

也可以同时把宽度尺寸设置为MATCH_CONSTRAINT (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)的宽.

链条

链条提供一组行为在一条单轴上(横向或者竖向),其他轴可以有独立的约束。

Fig. 9 - Chain

创建一个链条

如果通过双向连接将一组小部件连接到一起,就会被认为是一个链条。

Fig. 10 - Chain Head

链头

链条由链的第一个元素上的属性控制,链头是水平链的最左边的部件,也是垂直链的最顶层的部件。

边距

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

链条样式

当在链的第一个元素上设置属性layout_constraintHorizontal_chainStyle 或者 layout_constraintVertical_chainStyle时,链条的行为将根据指定的样式进行更改(默认是CHAIN_SPREAD)。

  • CHAIN_SPREAD – 这些元素将会分散开来,相同间距 (default style)
    Weighted chain – 在 CHAIN_SPREAD 模式下, 如果一些部件设置成 MATCH_CONSTRAINT, 他们将分配剩余空间(类似layout_weight)
    CHAIN_SPREAD_INSIDE – 类似,但是链的端点不会分散开来
    CHAIN_PACKED – 链条的组成部分将被打包在一起。然后,孩子的水平或垂直偏差属性会影响填充元素的位置

Fig. 11 - Chains Styles

Weighted chains

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

边距和链条 (在1.1)

当在链条上使用margins时,margins是附加的。
例如,在水平链上,如果一个元素定义了10dp的右边距,而下一个元素定义了5dp的左边距,那么这两个元素之间的边距是15 dp。
当计算链用来定位物品的剩余空间时,一个物品加上它的边缘被考虑在一起。剩余的空间不包含边距。

虚拟辅助对象

除了前面详细介绍的内在功能之外,你还可以在约束布局中使用特殊的助手对象来帮助您进行布局。目前,Guideline 允许您创建相对于约束布局容器的水平和垂直的指导方针。然后,可以通过将小部件限制在这些指导方针中来定位。在1.1中,也加入了Barrier(障碍)和Group(组)。

Guideline

工具类表示约束布局的指导助手对象。辅助对象不会显示在设备上。他们仅仅使用在约束布局内部。

Guideline分为 横向和竖向:
* 竖向是宽为0,高是父的约束布局的高
* 横向是高为0,宽是父的约束布局的宽

用3种方式定位一个Guideline
* 在布局中指定左或者顶部的距离(layout_constraintGuide_begin)
* 在布局中指定右边左或者底部的距离 (layout_constraintGuide_end)
* 在布局中指定一个宽高的百分比 (layout_constraintGuide_percent)

部件可以被Guideline约束,允许多个部件可以很容易地从一个Guideline中定位,或者允许使用百分比定位来进行响应式布局行为。

Barrier(界线)

一个Barrier可以引入多个部件作为输入,然后建立一条虚拟引导线,这条线基于基于最大部件在一条指定的边上。例如一条左边界线对齐所有的views

     <android.support.constraint.Barrier
              android:id="@+id/barrier"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              app:barrierDirection="start"
              app:constraint_referenced_ids="button1,button2" />

Group(组)

这个类控制一组引用部件的可见度。部件引用添加通过逗号分开。例如:

     <android.support.constraint.Group
              android:id="@+id/group"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:visibility="visible"
              app:constraint_referenced_ids="button4,button9" />

该组的可见性将应用于所引用的部件。这是一种方便的方法,可以轻松地隐藏/显示一组小部件,而无需以编程方式维护该集合。

Multiple groups

多个群组可以引用相同的小部件——在这种情况下,XML声明顺序将定义最终可见性状态(最后声明的组将拥有最后一个单词)

优化器(1.1版)

在1.1的版暴露了约束优化器,你可以通过添加标签app:layout_optimizationLevel指定哪些优化,用来应用到ConstraintLayout元素中:

  • standard: 只对direct和barrier约束进行优化
  • direct: 优化直接的约束
  • barrier:优化barrier的约束
  • chain:优化链条的约束 (实验性的)
  • dimensions:优化尺寸的测量(实验性的),减少匹配约束元素的测量的次数。
    这个属性是一个掩码,所以您可以决定打开或关闭特定的优化,列出你想要的,例如
app:layout_optimizationLevel="direct|barrier|chain"
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值