ConstraintLayout详解

本文详细介绍了Android中的ConstraintLayout,包括其解决布局嵌套问题、提高性能的特点,以及如何进行相对定位、角度定位、使用Margin、居中偏移、尺寸约束和链的设置。此外,还讲解了辅助工具的使用,如Barrier、Group、Placeholder和Guideline,帮助开发者更好地理解和运用ConstraintLayout。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.介绍

约束布局ConstraintLayout本身就是一个ViewGroup,它用来解决布局嵌套过多的问题(嵌套越多,绘制消耗的时间越长),以灵活的方式定位/调整小部件(API 9以上均可使用),相比RelativeLayout更灵活,性能更加的出色,更好的适配屏幕大小不同的机型。Android Studio 2.3开始默认创建Activity是都是使用它。

2.使用

使用它也非常的简单,高版本的AS通常都会自动的添加它的依赖,如果未添加依赖在app/build.gradle中添加相应的依赖即可。

 implementation 'com.android.support.constraint:constraint-layout:1.1.3'
2.1 相对定位

即一个组件相对于另一个组件的约束,非常的好理解(与RelativeLayout非常的类似)。

例:要实现B在A的右侧:
在这里插入图片描述
按钮A在按钮B的右侧,也可以理解为按钮B的左侧位于按钮A的右侧;其他的方位都一样。我们在代码中的表示如下:

 <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintLeft_toRightOf="@id/btn1" />

其中最关键的属性为app:layout_constraintLeft_toRightOf="@id/btn1",代表按钮B的左侧位于按钮A的右侧

其中常用的属性还有:

 // 值可以为parent,意思就是A的左侧位于父布局的左侧(top_top|bottom_bottom等一样)
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

引用官方的一张图来说明这些属性:
在这里插入图片描述

比较特殊的有layout_constraintBaseline_toBaselineOf,如图所示,两个Button的高度不一致,但是又希望他们文本对齐,这个时候就可以使用layout_constraintBaseline_toBaselineOf保证文字相对齐:
在这里插入图片描述

<Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:text="Button3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:text="Button4"
        app:layout_constraintBaseline_toBaselineOf="@id/btn3"
        app:layout_constraintLeft_toRightOf="@id/btn3" />
2.2 角度定位

角度定位指的是利用角度以及距离决定某些控件中心点的坐标。
三个属性为:

  1. app:layout_constraintCircle="@id/btn3" 指定相对于哪个控件
  2. app:layout_constraintCircleAngle="160" 角度
  3. app:layout_constraintCircleRadius="150dp" 中心点的距离

其中的关系如下图所示:
在这里插入图片描述
例子:按钮5在按钮3的160度方向距离为150dp

<Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:text="Button3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 <Button
        android:id="@+id/btn5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button5"
        app:layout_constraintCircle="@id/btn3"
        app:layout_constraintCircleAngle="160"
        app:layout_constraintCircleRadius="150dp" />

效果图:
在这里插入图片描述

2.3 Margin

使用Margin时,用法与其他布局的一致,前提条件是:必须指定了相对应的约束,Margin值只能大于等于0

唯一特殊的地方:在对应约束的控件隐藏时,相当于一个点,可使用如下Margin来设置隐藏后的Margin值

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
2.4 居中偏移

如何实现居中:即利用相对定位中的4个属性即可

 app:layout_constraintBottom_toBottomOf="parent"
 app:layout_constraintLeft_toLeftOf="parent"
 app:layout_constraintRight_toRightOf="parent"
 app:layout_constraintTop_toTopOf="parent"

偏移(Bias): 使用app:layout_constraintHorizontal_bias="0.3"属性即可(值在0-1之间)

1.layout_constraintHorizontal_bias 水平偏移
2. layout_constraintVertical_bias 垂直偏移

上下居中,水平偏移为0.3
在这里插入图片描述

2.5 尺寸约束

提供了一下四种方式:

  1. 固定值
  2. wrap_content,自己进行计算
    当控件的高度或宽度为wrap_content时,可以使用下列属性来控制最大、最小的高度或宽度:
    android:minWidth 最小的宽度
    android:minHeight 最小的高度
    android:maxWidth 最大的宽度
    android:maxHeight 最大的高度
  3. 使用0dp 官方不推荐在ConstraintLayout中使用match_parent,可设置0dp(MATCH_CONSTRAINT)配合代替match_parent
    宽高比:当宽或高至少一个被设置为0dp时,可通过属性layout_constraintDimensionRatio设置宽高比还可以在值的前面加上W或者H
    app:layout_constraintDimensionRatio="W,2:1" 宽高比2:1
    app:layout_constraintDimensionRatio="H,2:1" 高宽比2:1
 <Button
        android:id="@+id/btn6"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button6"
        android:layout_marginStart="20dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn5" />

 <!-- 通过layout_constraintDimensionRatio 设置宽高比 -->
    <Button
        android:id="@+id/btn7"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button7"
        app:layout_constraintDimensionRatio="W,2:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn6" />

效果图:
在这里插入图片描述

2.6 链

如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)。
在这里插入图片描述
一条链的第一个控件是这条链的链头,我们可以在链头中设置链的Style,相关的Style有:
app:layout_constraintHorizontal_chainStyle="spread|spread_inside|packed"
app:layout_constraintVertical_chainStyle="spread|spread_inside|packed"

  1. CHAIN_SPREAD : 默认模式(展开元素)
  2. CHAIN_SPREAD_INSIDE :展开元素,两端靠近parent边缘
  3. CHAIN_PACKED :控件被整合在一起
  4. Weighted Chain: 权重链,当宽度或者高度被设置成0dp时,layout_constraintHorizontal_weight 和 layout_constraintVertical_weight控制所占比例

注意:在链中的元素上使用边距时,边距是相加的。A Margin right 10,B Margin left 5,total 15
Style的形式使用下图表示:
在这里插入图片描述
使用案例:

 <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/btn2" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintLeft_toRightOf="@id/btn1"
        app:layout_constraintRight_toLeftOf="@id/btn3" />

    <Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3"
        app:layout_constraintLeft_toRightOf="@id/btn2"
        app:layout_constraintRight_toRightOf="parent" />

packed模式
在这里插入图片描述
spread模式
在这里插入图片描述
spread_inside模式
在这里插入图片描述
Weighted Chain模式,必须存在一个0dp
在这里插入图片描述

3.辅助工具的使用

3.1 Optimizer

当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:

  1. none 无优化
  2. Standard 仅优化直接约束/屏障约束(默认)
  3. Direct 优化直接约束
  4. Barrier 优化屏障约束
  5. Chain 优化链约束
  6. Dimensions 优化尺寸测量
3.2 Barrier(屏障)

详参:https://developer.android.google.cn/reference/android/support/constraint/Barrier
A与B的宽度未知,现在让C约束在A或者B的右侧都不对;这种情况可用Barrier解决,它相当于在AB的一侧与C之间加了一个屏障。
在这里插入图片描述
使用Barrier后如下图(A B都在屏障内):
在这里插入图片描述

主要的属性:

app:barrierDirection="end|top|bottom|start|left|right"等设置屏障的位置
app:constraint_referenced_ids=””设置屏障引用的控件,多个值时用’,’隔开

例子:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="MissingConstraints">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:text="Button4"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginTop="6dp"
        android:text="Button5 Button5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button1" />

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

    <TextView
        android:id="@+id/textView3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="10dp"
        android:text="为了看到整体的效果,可以切换语言,
        此时你会看到Barrier会自动位于较宽的那个textView后面,
        也就间接让 textView3 也位于了正确的位置"
        app:layout_constraintLeft_toRightOf="@id/barrier"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

效果:
在这里插入图片描述

最终在C中引用Barrier的约束即可,使用后不管A或者B的宽度如何变化,C始终都位于屏障的右侧

3.3 Group

详参:https://developer.android.google.cn/reference/android/support/constraint/Group
主要作用:把控件归类为一组,更加便捷的管理显示与否等

控件隐藏前:
在这里插入图片描述

使用Group,并且添加相关的依赖:app:constraint_referenced_ids="btn2,btn3"关联关系

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:ignore="MissingConstraints">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintLeft_toRightOf="@id/btn1" />

    <Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3"
        app:layout_constraintLeft_toRightOf="@id/btn2" />

    <android.support.constraint.Group
        app:constraint_referenced_ids="btn2,btn3"
        android:visibility="visible"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>

控件隐藏后:
在这里插入图片描述

3.4 Placeholder

详参:https://developer.android.google.cn/reference/android/support/constraint/Placeholder
占位符,可使用setContent设置另一个控件的id,使这个控件移动到占位符的位置.
通过app:content="@+id/btn1"属性设置要移动的View
案例:设置Button在右上角,设置Placeholder在左下角,设置content后,Button移动到Placeholder的位置(左下角)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:ignore="MissingConstraints">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.constraint.Placeholder
        android:id="@+id/ph"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:content="@+id/btn1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent" />


</android.support.constraint.ConstraintLayout>

效果:

在这里插入图片描述
在这里插入图片描述

3.5 Guideline

详参:https://developer.android.google.cn/reference/android/support/constraint/Guideline
布局辅助线,预览的时候帮助我们完成布局(不显示在界面上)
主要属性:
android:orientation="horizontal|vertical"
app:layout_constraintGuide_end = “50dp” 结束位置
app:layout_constraintGuide_begin = “50dp” 开始位置
app:layout_constraintGuide_percent="0.6"距离顶部的百分比(orientation = horizontal时则为距离左边)

例子:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:ignore="MissingConstraints">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <android.support.constraint.Guideline
        android:id="@+id/line1"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="50dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <android.support.constraint.Guideline
        android:id="@+id/line2"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <android.support.constraint.Guideline
        android:id="@+id/line3"
        android:orientation="horizontal"
        app:layout_constraintGuide_end="50dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>

效果:
在这里插入图片描述

ConstraintLayout 的使用就简单介绍到这里

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值