constraintlayout使用总结

约束布局的用法

ConStraintlayout是android.view.ViewGroup,允许我们灵活的定位和调整窗口小部件的大小。

当前可以使用多种约束:

  • Relative positioning(相对定位)
  • Margins(相对定位余量)
  • Centering positioning(居中定位)
  • Circular positioning(圆形定位)
  • Visblity behavior(可见性行为)
  • Dimension constrains(尺寸限制)
  • Chains(链条)
  • Virtual Helpers objects(虚拟助手对象)
  • Optimizer(优化器)

相对定位

可以在水平和垂直轴上约束小部件。

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

下图是将按钮B定位在按钮A的右侧(采用官网图片):


相对定位
<Button 
android:id="@+id/buttonA" 
... />

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

这种方式告诉系统我们希望将按钮B的左侧限制为按钮A的右侧,这种位置限制意味着系统将尝试使两侧共享同一位置。


image

可用约束列表如下:

  • 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)

Margins

image

如果设置了边距,则会将他们应用于相应的约束,从而将边距强制为目标端与源端之间的空间。可以使用通常的布局边距属性来达到此效果:

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

连接到GONE小部件时的边距

当位置限制目标的可见性为View.GONE,可以使用下面属性设置其他边距值:

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

居中定位和偏向

有以下代码:

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

除非ConStraintLayout碰巧大小和Button完全相同,否则无法同时满足两个约束。


image

这种情况下,约束的作用就像反向作用力一样将小部件平均拉开。这样小部件将最终位于父容器的中心。类似的应用于垂直约束。

偏压

上面是居中定位,如果想让小部件偏到另一侧,可以使用bias属性调整位置。

  • layout_constrainHorizontal
  • layout_constrainVertical_bias


    image

    如下代码,使左侧具有30%的偏差,而不是默认的50%,这样左侧将更短,小部件更偏向左侧。

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

通过使用偏见,可以更好的适应屏幕尺寸变化的用户界面。

圆形定位

可以以一定角度和距离相对于另一个窗口小部件中心限制窗口小部件中心,这可以使小部件放在圆上,使用如下属性:

  • layout_constraintCircle:引用另一个小部件
  • layout_constraintCircleRadius:到另一个小部件中心的距离
  • layout_constraintCircleAngle:小部件应处于哪个角度


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

可见性行为

ConstraintLayout中标记的小部件处理为View.GONE时,此部件通常不会显示,也不是布局本身的一部分。但作为布局计算而言,GONE小部件仍然是其中的一部分,但是有一个重要的区别:

  • 对于布局传递,其尺寸将被视为0(基本上会被解析为一个点)
  • 如果他们对其他小部件有约束,则他们仍然会受到尊重,但是任何边距都等于0。


    image

尺寸限制

最小尺寸

使用wrap_content的时候,可以使用如下来限制控件大小。

  • android:minWidth 设置布局的最小宽度
  • android:minHeight 设置布局的最小高度
  • android:maxWidth 设置布局的最大宽度
  • android:maxHeigth 设置布局的最大高度

小部件尺寸约束

可以通过3种不同的方式设置android:layout_widht和android:layout_height属性来指定小部件的尺寸:

  • 使用特定尺寸
  • 使用wrap_content,这要求小部件计算自己的大小
  • 使用0dp,等同于match_constraint

不建议ConstraintLayout布局中包含的小部件用match_partent,可通过match_constraint将相应的左/右或上/下约束设置来实现类似parent的行为。

match_constraint

将尺寸设置为match_constraint,默认是占用所有可用空间,可使用其他几个修饰符:

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

尺寸百分比

使用方法:

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

宽高比

可以将小部件的一个尺寸定义为另一个尺寸的比例,所以至少将一个约束尺寸设置为0dp,通过属性layout_constraintDimensionRation设置为给定的比率。例如:

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

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

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

如果两个尺寸都为match_constraint,系统将设置满足所有约束并维持指定长宽比的最大尺寸。

假设控件A在水平的左右方向都存在约束,垂直方向只有一条约束。相对于垂直方向,A在水平方向上的宽度比较固定(等于屏幕宽度),所以高度会根据比例跟着变化。

假设控件A在水平方向以及垂直方向都有存在约束,那就可以通添加w或h来指定约束方向。

app:layout_constraintDimensionRatio="w,1:2"  //或  "h,1:2"
"w,1:2"表示 宽度根据高度变化而变化,且宽高比依旧是1:2
"h,1:2"表示 高度根据宽度变化而变化,且宽高比依旧是1:2
W/H 是用于指定约束方向

Chain

链式表示方式就类似于水平方向、垂直方向上小部件按比重分配空间,具体类型可见下图:


image

通过layout_constraintHorizontal_weight属性来达到不同的效果。

layout_constraintVertical_chainStyle = "spread_inside|spread|packed"

实现spread效果代码如下:

    <Button
        android:id="@+id/buttonA"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="buttonA"
        app:layout_constraintEnd_toStartOf="@+id/buttonB"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/buttonB"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="buttonB"
        app:layout_constraintEnd_toStartOf="@+id/buttonC"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/buttonA"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/buttonC"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="buttonC"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/buttonB"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="MissingConstraints" />

可以用chain工具自动生成布局代码。刚开始手动写的时候没有加bias属性布局没有反应。

参考文章

官方文档

constraintlayout学起来!

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