这两天跟着Google的官方文档学习了一下ConstraintLayout布局,相较于RelativeLayout来说最大的好处是ConstrainLayout布局可以减少嵌套,提升性能。
参考:解析ConstraintLayout的性能优势 https://mp.weixin.qq.com/s/gGR2itbY7hh9fo61SxaMQQ?
相对定位
ConstraintLayout使用了相对定位,通过和父控件和其他控件来约束控件。
app:layout_constraintLeft_toLeftOf:控件左边相对于其他控件左边的约束
app:layout_constraintLeft_toRightOf:控件左边相对于其他控件右边的约束
app:layout_constraintRight_toLeftOf:控件右边相对于其他控件左边的约束
app:layout_constraintRight_toRightOf:控件右边相对于其他控件的右边的约束
app:layout_constraintTop_toTopOf
app:layout_constraintTop_toBottomOf
app:layout_constraintBottom_toTopOf
app:layout_constraintBottom_toBottomOf
app:layout_constraintBaseline_toBaselineOf
app:layout_constraintStart_toEndOf
app:layout_constraintStart_toStartOf
app:layout_constraintEnd_toStartOf
app:layout_constraintEnd_toEndOf
元素的约束效果如下所示:
代码如下:
<TextView android:layout_width="60dp" android:layout_height="60dp" android:text="textview1" android:id="@+id/textview1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintHorizontal_bias="0.3" android:background="#0fffff" />
以上元素默认的约束权重为0.5,也可以通过 app:layout_constraintHorizontal_bias 或者 app:layout_constrainVertical_bias 属性来对控件进行水平方向或竖直方向上的偏移操作。
同时,ConstraintLayout也支持margin元素的使用,当使用margin时,控件相应方向上的控件约束将会排除掉margin中定义的距离之后再开始对控件进行约束,效果如下图:
代码如下:
<TextView android:layout_width="60dp" android:layout_height="60dp" android:text="textview1" android:id="@+id/textview1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintHorizontal_bias="0.3" android:background="#0fffff" android:layout_marginLeft="50dp" />
能见度行为
ConstraintLayout允许控件和另外一些不可见得控件进行约束,也给了一些元素来防止某些控件变得不可见时约束的失效,属性元素如下:
layout_goneMarginTop
layout_goneMarginBottom
layout_goneMarginRight
layout_goneMarginLeft
layout_goneMarginEnd
layout_goneMarginStart
效果如下所示:
代码如下:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview2" android:background="@color/colorAccent" app:layout_constraintBottom_toTopOf="@+id/textview1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_goneMarginBottom="150dp" />
在代码中加上最后一行代码,即从左图效果变为右图效果,由于在ConstraintLayout布局中,gone属性的元素对其他元素依旧具有约束效果,只是所有边界均会变成0,为了防止某些控件在变为gone属性的时候其他控件位置显示偏移太多,可以设置gone元素来指定当该方向的约束指向不可见控件时与父控件的最短距离。另外goneMargin元素只会在有gone属性控件约束的情况下生效,当约束来自非gone的控件时该元素不生效。
圆形定位
ConstraintLayout允许控件相对于其他控件的中心来进行定位,属性元素如下:
app:layout_constraintCircle
:引用另一个小部件id
app:layout_constraintCircleRadius
*到另一个小部件中心的距离
app:layout_constraintCircleAngle
:小部件应该处于哪个角度(以度为单位,从0到360)
圆形定位的效果如下图所示:
代码如下:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview2" android:background="@color/colorAccent" app:layout_constraintCircleRadius="100dp" app:layout_constraintCircle="@id/textview1" app:layout_constraintCircleAngle="45" />
控件的约束
控件自身的约束包括强制约束、最小最大约束、匹配约束尺寸
属性元素如下:
app:layout_constrainedWidth=”true|false” 宽度的强制约束
app:layout_constrainedHeight=”true|false” 高度的强制约束
layout_constraintWidth_min 设置控件宽度的最小值
layout_constraintHeight_min 设置控件高度的最小值
layout_constraintWidth_max 设置控件宽度的最大值
layout_constraintHeight_max 设置控件高度的最大值
layout_constraintWidth_percent 设置控件宽度为父控件高度的百分比
layout_constraintHeight_percent 设置控件高度为父控件高度的百分比
另外控件的最大最小值也可以通过百分比来设置,需要设置如下属性:
将 layout_Width 或 layout_Height 设置为 0 dp(如果是在design界面拖动则为 match_constraint ),通过
app:layout_constraintWidth_default="percent"
app:layout_constraintHeight_default="percent"
来设置默认百分比,之后将
layout_constraintWidth_percent
layout_constraintHeight_percent
设置为0到1之间的值。
控件本身也可以对高度和宽度进行约束,通过属性
layout_constraintDimensionRatio "H,1:1"
来设置高度和宽度的比率,至少需要将一个受到限制的维度设置为 0 dp,如果需要限定特定的维度,则需要在比率之前加上H或W来进行限制。
另外在ConstraintLayout布局中不推荐使用 match_parent 的属性,会使得其他约束条件无效。
链
ConstraintLayout中,如果有两个控件之间相互约束,则它们就成为一个链,链的第一个元素即为链头,可以在链头中定义链的形式,如下图所示:
值得注意的是,Google官方文档中特别说明了一点,如果一个链中的两个元素,在它们中间都有一个margin距离,那么这个距离将会是两个margin定义的距离的加和。