Constraintlayout全解析

android:text=“按钮1”

app:layout_constraintHorizontal_bias=“0.3”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”/>

</android.support.constraint.ConstraintLayout>

复制代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以看到, 左右有 2 根约束线. 左侧短一些. 那么就偏向于左侧

五、Circular positioning (Added in 1.1)

翻译为: 圆形的定位 ?

这个就比较牛逼了, 可以以角度和距离约束某个 view 中心相对于另一个 view 的中心,

可能比较抽象, 来看看谷歌画的图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

他的属性有:

layout_constraintCircle :引用另一个小部件ID

layout_constraintCircleRadius :到其他小部件中心的距离

layout_constraintCircleAngle :小部件应该处于哪个角度(以度为单位,从0到360)

复制代码

举个例子:

<Button

android:id=“@+id/btn1”

android:text=“按钮1”/>

<Button

android:text=“按钮2”

app:layout_constraintCircle=“@+id/btn1”

app:layout_constraintCircleRadius=“100dp”

app:layout_constraintCircleAngle=“145”/>

复制代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

六、Visibility behavior 可见性行为

当一个 View 在 ConstraintLayout 中被设置为 gone, 那么你可以把它当做一个点 (这个 view 所有的 margin 都将失效). 这个点是假设是实际存在的.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

举个例子:

<Button

android:id=“@+id/btn1”

android:text=“按钮1”

android:textSize=“26sp”/>

<Button

android:id=“@+id/btn2”

android:layout_marginStart=“20dp”

android:text=“按钮2”

android:visibility=“gone”

app:layout_constraintLeft_toRightOf=“@+id/btn1”/>

<Button

android:id=“@+id/btn3”

android:layout_marginStart=“20dp”

android:text=“按钮3”

app:layout_constraintLeft_toRightOf=“@+id/btn2”/>

复制代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以看到, 按钮 3 和按钮 1 中间的 margin 只有 20.

再举个例子:

<Button

android:id=“@+id/btn2”

android:layout_marginStart=“20dp”

android:text=“按钮2”

app:layout_constraintBottom_toBottomOf=“parent”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toTopOf=“parent”/>

<Button

android:id=“@+id/btn3”

android:text=“按钮3”

app:layout_constraintLeft_toRightOf=“@+id/btn2”

app:layout_constraintTop_toTopOf=“@+id/btn2”

app:layout_constraintBottom_toBottomOf=“@+id/btn2”/>

复制代码

我将按钮 3 放到按钮 2 的右侧, 这时是没有给按钮 2 加android:visibility="gone"的.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们来给按钮 2 加上android:visibility="gone"

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这时, 按钮 2 相当于缩小成一个点, 那么按钮 3 还是在他的右侧不离不弃.

七、Dimensions constraints 尺寸限制

在 ConstraintLayout 中, 可以给一个 view 设置最小和最大尺寸.

属性如下 (这些属性只有在给出的宽度或高度为 wrap_content 时才会生效):

android:minWidth 设置布局的最小宽度

android:minHeight 设置布局的最小高度

android:maxWidth 设置布局的最大宽度

android:maxHeight 设置布局的最大高度

复制代码

八、Widgets dimension constraints 宽高约束

平时我们使用android:layout_width和 android:layout_height来指定 view 的宽和高.

在 ConstraintLayout 中也是一样, 只不过多了一个 0dp.

  • 使用长度, 例如

  • 使用 wrap_content,view 计算自己的大小

  • 使用 0dp,相当于 “MATCH_CONSTRAINT”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面是例子

<Button

android:id=“@+id/btn1”

android:layout_width=“100dp”

android:layout_height=“wrap_content”

android:text=“按钮1”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”/>

<Button

android:id=“@+id/btn2”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:text=“按钮2”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toBottomOf=“@+id/btn1”/>

<Button

android:id=“@+id/btn3”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:layout_marginStart=“60dp”

android:text=“按钮3”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toBottomOf=“@+id/btn2”/>

复制代码

展示出来的是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

当一个 view 的宽或高, 设置成 wrap_content 时, 如果里面的内容实在特别宽的时候, 他的约束会出现问题. 我们来看一个小栗子:

<Button

android:id=“@+id/btn1”

android:layout_width=“100dp”

android:layout_height=“wrap_content”

android:text=“Q”/>

<Button

android:id=“@+id/btn2”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV”

app:layout_constraintLeft_toRightOf=“@id/btn1”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toBottomOf=“@id/btn1”/>

复制代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从右侧的图片可以看出, 按钮 2 里面的内容确实是在按钮 1 的内容的右侧. 但是按钮 2 整个来说, 却是没有整个的在按钮 1 的右侧.

这时需要用到下面 2 个属性

app:layout_constrainedWidth=”true|false”

app:layout_constrainedHeight=”true|false”

复制代码

给按钮 2 加一个app:layout_constrainedWidth="true", 来看效果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

哈哈, 又看到了我们想要的效果. 爽歪歪.

十、MATCH_CONSTRAINT 尺寸(在 1.1 中添加)

当一个 view 的长宽设置为 MATCH_CONSTRAINT(即 0dp) 时, 默认是使该 view 占用所有的可用的空间. 这里有几个额外的属性

layout_constraintWidth_min和layout_constraintHeight_min:将设置此维度的最小大小

layout_constraintWidth_max和layout_constraintHeight_max:将设置此维度的最大大小

layout_constraintWidth_percent和layout_constraintHeight_percent:将此维度的大小设置为父级的百分比

复制代码

这里简单举个百分比的例子: 居中并且 view 的宽是父亲的一半

<Button

android:id=“@+id/btn1”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:text=“Q”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintWidth_percent=“0.5”/>

复制代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

It’s so easy! 这极大的减少了我们的工作量.

注意

  • 百分比布局是必须和 MATCH_CONSTRAINT(0dp) 一起使用

  • layout_constraintWidth_percent 或layout_constraintHeight_percent属性设置为 0 到 1 之间的值

十一、按比例设置宽高 (Ratio)

可以设置 View 的宽高比例, 需要将至少一个约束维度设置为 0dp(即MATCH_CONSTRAINT), 再设置layout_constraintDimensionRatio.

举例子:

<Button

android:layout_width=“0dp”

android:layout_height=“0dp”

android:text=“按钮”

app:layout_constraintDimensionRatio=“16:9”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toTopOf=“parent”/>

复制代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该比率可表示为:

  • 浮点值,表示宽度和高度之间的比率

  • “宽度:高度” 形式的比率

如果两个尺寸都设置为 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 的比例设置按钮的高度,而按钮的宽度将匹配父项的约束。

十二、Chains(链)

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

  • CHAIN_SPREAD - 元素将展开(默认样式)

  • 加权链接 CHAIN_SPREAD 模式,如果设置了一些小部件 MATCH_CONSTRAINT,它们将分割可用空间

  • CHAIN_SPREAD_INSIDE - 类似,但链的端点不会分散

  • CHAIN_PACKED - 链条的元素将被包装在一起。然后,子项的水平或垂直偏差属性将影响打包元素的定位

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面是一个类似 LinearLayout 的 weight 的效果, 需要用到layout_constraintHorizontal_weight属性:

<Button

android:id=“@+id/btn1”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:text=“A”

app:layout_constraintEnd_toStartOf=“@id/btn2”

app:layout_constraintHorizontal_chainStyle=“spread”

app:layout_constraintHorizontal_weight=“1”

app:layout_constraintStart_toStartOf=“parent”/>

<Button

android:id=“@+id/btn2”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:text=“按钮2”

app:layout_constraintEnd_toStartOf=“@id/btn3”

app:layout_constraintHorizontal_weight=“2”

app:layout_constraintStart_toEndOf=“@id/btn1”/>

<Button

android:id=“@+id/btn3”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:text=“问问”

app:layout_constraintEnd_toEndOf=“parent”

app:layout_constraintHorizontal_weight=“3”

app:layout_constraintStart_toEndOf=“@id/btn2”/>

复制代码

例子的效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

十三、Guideline

这是一个虚拟视图

Guideline 可以创建相对于 ConstraintLayout 的水平或者垂直准线. 这根辅助线, 有时候可以帮助我们定位.

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

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

layout_constraintGuide_percent 距离父亲宽度或高度的百分比(取值范围0-1)

复制代码

我们拿辅助线干嘛??? 比如有时候, 可能会有这样的需求, 有两个按钮, 在屏幕中央一左一右. 如果是以前的话, 我会搞一个 LinearLayout,. 然后将 LinearLayout 居中, 然后按钮一左一右.

效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们使用 Guideline 的话, 就超级方便了, 看代码:

<android.support.constraint.Guideline

android:id=“@+id/gl_center”

android:layout_width=“0dp”

android:layout_height=“wrap_content”

android:orientation=“vertical”

app:layout_constraintGuide_percent=“0.5”/>

<Button

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“按钮1”

app:layout_constraintEnd_toStartOf=“@id/gl_center”/>

<Button

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“按钮2”

app:layout_constraintLeft_toRightOf=“@id/gl_center”/>

复制代码

十四、Barrier

虚拟视图

Barrier 是一个类似于屏障的东西. 它和 Guideline 比起来更加灵活. 它可以用来约束多个 view.

比如下面的姓名和联系方式, 右侧的 EditText 是肯定需要左侧对齐的, 左侧的 2 个 TextView 可以看成一个整体, Barrier 会在最宽的那个 TextView 的右边, 然后右侧的 EditText 在 Barrier 的右侧.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Barrier 有 2 个属性

  • barrierDirection,取值有 top、bottom、left、right、start、end,用于控制 Barrier 相对于给定的 View 的位置。比如在上面的栗子中,Barrier 应该在 姓名 TextView 的右侧,因此这里取值 right(也可 end,可随意使用. 这个 right 和 end 的问题, 其实在 RelativeLayout 中就有体现, 在 RelativeLayout 中写 left 或者 right 时会给你一个警告, 让你换成 start 和 end)。

  • constraint_referenced_ids,取值是要依赖的控件的 id(不需要 @+id/)。Barrier 将会使用 ids 中最大的一个的宽(高)作为自己的位置。

ps: 这个东西有一个小坑, 如果你写完代码, 发现没什么问题, 但是预览出来的效果却不是你想要的. 这时, 运行一下程序即可. 然后预览就正常了, 在手机上展示的也是正常的.

例子的代码如下 (如果预览不正确, 那么一定要运行一下, 不要怀疑是自己代码写错了):

<TextView

android:id=“@+id/tv_name”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“姓名:”

app:layout_constraintBottom_toBottomOf=“@id/tvTitleText”/>

<TextView

android:id=“@+id/tv_phone”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“联系方式:”

app:layout_constraintBottom_toBottomOf=“@id/tvContentText”

app:layout_constraintTop_toBottomOf=“@+id/tv_name”/>

<EditText

android:id=“@+id/tvTitleText”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:background=“null”

android:text=“张三”

android:textSize=“14sp”

app:layout_constraintStart_toEndOf=“@+id/barrier2”/>

<EditText

android:id=“@+id/tvContentText”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:background=“null”

android:text=“xxxxxxxxxxxxxxx”

android:textSize=“14sp”

app:layout_constraintStart_toEndOf=“@+id/barrier2”

app:layout_constraintTop_toBottomOf=“@+id/tvTitleText”/>

<android.support.constraint.Barrier

android:id=“@+id/barrier2”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

app:barrierDirection=“right”

app:constraint_referenced_ids=“tv_name,tv_phone”/>

复制代码

十五、Group

固定思议, 这是一个组. 这也是一个虚拟视图.

可以把 View 放到里面, 然后 Group 可以同时控制这些 view 的隐藏.

<android.support.constraint.Group

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:visibility=“gone”

app:constraint_referenced_ids=“btn1,btn2”/>

<Button

android:id=“@+id/btn1”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“按钮1”/>

<Button

android:id=“@+id/btn2”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“按钮2”

app:layout_constraintTop_toBottomOf=“@id/btn1”/>

复制代码

  • Group 有一个属性constraint_referenced_ids, 可以将那些需要同时隐藏的 view 丢进去.

  • 别将 view 放 Group 包起来. 这样会报错, 因为 Group 只是一个不执行 onDraw() 的 View.

  • 使用多个 Group 时,尽量不要将某个 View 重复的放在 多个 Group 中,实测可能会导致隐藏失效.

十六、何为虚拟视图

上面我们列举的虚拟视图一共有:

  • Guideline

  • Barrier

  • Group

来我们看看源码

//Guideline

public class Guideline extends View {

public Guideline(Context context) {

super(context);

//这个8是什么呢?

//public static final int GONE = 0x00000008;

//其实是View.GONE的值

super.setVisibility(8);

}

public Guideline(Context context, AttributeSet attrs) {

super(context, attrs);

super.setVisibility(8);

}

public Guideline(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

super.setVisibility(8);

}

public Guideline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr);

super.setVisibility(8);

}

//可见性永远为GONE

public void setVisibility(int visibility) {

}

//没有绘画

public void draw(Canvas canvas) {

}

//大小永远为0

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

this.setMeasuredDimension(0, 0);

}

复制代码

学习交流

群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
ublic Guideline(Context context, AttributeSet attrs) {

super(context, attrs);

super.setVisibility(8);

}

public Guideline(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

super.setVisibility(8);

}

public Guideline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr);

super.setVisibility(8);

}

//可见性永远为GONE

public void setVisibility(int visibility) {

}

//没有绘画

public void draw(Canvas canvas) {

}

//大小永远为0

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

this.setMeasuredDimension(0, 0);

}

复制代码

学习交流

[外链图片转存中…(img-vvCx3GzP-1714661367633)]

[外链图片转存中…(img-EMd6wNb1-1714661367635)]

群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值