Android ConstraintLayout从入门到精通

深入解析ConstraintLayout特性,包括依赖引入、基本使用、约束详解、尺寸控制、链控制及虚拟辅助对象,提升Android布局效率。

一、前言

    大家都知道,在Android中是通过布局来定义应用中的界面结构,随着版本的更新迭代,有些布局类型因为适用性退出了历史的舞台,例如:AbsoluteLayout。也增了一些布局类型,例如本文提到的 ConstraintLayout (ConstraintLayout 是 Android Jetpack 的一部分)。

    在 Android 开发过程中,针对复杂的布局,以往的实现方式只能通过多种类型的布局叠加组合实现,但是这样存在一个问题,就是布局的嵌套层次过多,会影响UI的绘制性能,降低应用的品质。 ConstraintLayout 可以在无嵌套视图组的前提下,实现扁平视图层次结构,创建复杂的大型布局。它与 RelativeLayout 相似,内部所有的视图均根据同级视图与父布局之间的关系进行布局,但其灵活性要远高于 RelativeLayout。

二、ConstraintLayout 的使用

2.1 引入依赖

    ConstraintLayout 是 Android Jetpack 的一部分,需要额外引入依赖包才能使用,在项目程序模块下的 build.gradle 文加下增加依赖。

// support包引入,如果项目使用其他support包,使用这个
implementation 'com.android.support.constraint:constraint-layout:1.1.3'

// androidx包引入,如果项目使用androidx时使用,跟support包引入只能选其一,否则会冲突
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7'

注意事项:确保您的 maven.google.com 代码库已在模块级 build.gradle 文件中声明(较新版的AndroidStudio新建项目都会自动加入,如果是很老的旧项目,请检查代码库配置)。

2.2 在布局中使用

    因为 ConstraintLayout 是 Android Jetpack 的一部分,所以引用以及属性使用,都跟系统控件有些不一样

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</android.support.constraint.ConstraintLayout>

说明:

  1. 非系统控件,在布局文件中使用需要使用类名全名(这跟自定义控件一样);
  2. 非系统控件,自定义的属性需要添加 xmlns:app="http://schemas.android.com/apk/res-auto" 引入属性(其中 app 是可以任意命名,但是不能用 android,因为这个已被系统使用。)

2.3 ConstraintLayout 的约束详解

    ConstraintLayout 布局主要通过相互约束来控制布局的,下面将会详细介绍下这些约束。

2.3.1 相对位置约束

    相对位置约束是指一个控件跟父级容器或者其他同级控件之间的相对位置,相对位置有以下几个要素(如下图所示):

  • 水平方向:left(左边)、right(右边)、start(起始边)、end(结束边)
  • 垂直方向:top(上边)、bottom(下边)、text baseline(文字基线,这个只对有文本的控件有效)

相对位置要素

说明:其实 leftstartrightend 是相同的。



控制相对位置约束的属性有以下这些:

  • 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:控件结束边与目标控件结束边的约束条件

示例

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
    <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_constraintTop_toBottomOf="@+id/btn1"/>

</androidx.constraintlayout.widget.ConstraintLayout>

效果:
相对位置约束

注意事项:相对位置约束的属性在使用过程中,部分属性之间是冲突的,在使用过程中要特别注意。例如:layout_constraintLeft_toLeftOflayout_constraintLeft_toRightOf,一个控件的左边不可能同时跟目标控件的左边和右边存在约束。

2.3.2 相对间距

    ConstraintLayout 的间距为什么说是相对的呢?因为设置的间距都是相对约束的目标控件的间距,如下图所示:Button2 左边对齐 Button1 的右边,所以,当 Button2 设置左间距 30dp 时,是相对 Button1 的右边。

相对间距

注意:如果控件居中显示,设置了间距之后,居中的位置也会相对变化(会线除去间距的位置之后再居中),关于在 ConstraintLayout 中居中的相关内容参考: 居中对齐

设置间距属性如下:

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

说明:设置间距的属性使用的是框架自带属性,不是 ConstraintLayout 自定义属性,所以以 android 为命名空间。

2.3.3 关联控件隐藏(View.GONE)时的间距

    关联控件隐藏(View.GONE)时的间距,跟相对间距类似,不同的是,他是在关联控件隐藏(View.GONE)之后才会生效。

示例:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
    <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_constraintTop_toBottomOf="@+id/btn1"
        android:layout_marginLeft="30dp"
        android:visibility="visible"/>
    <Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3"
        app:layout_constraintRight_toLeftOf="@+id/btn2"
        app:layout_constraintTop_toBottomOf="@+id/btn2"
        android:layout_marginTop="30dp"
        app:layout_goneMarginTop="100dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

效果:
关联控件隐藏间距

以上示例中,当 Button2 隐藏(gone)之后,Button3的上间距由原来的30dp变为了50dp,至于为什么Button3的位置会发生改变,这个参考:当依赖的控件隐藏(View.GONE)之后

2.3.4 居中对齐

    在ConstraintLayout里面的控件都是靠关联约束进行控制的,那么如何实现居中对齐呢?实现起来其实也很简单,只需两个方向同时设置关联控件就可以实现在两个关联点之间居中。

  • 水平居中:同时设置左、右两边的关联约束
  • 垂直居中: 同时设置上、下两边的关联约束

示例:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <Button
        android:id="@+id/btn1"
        android:layout_width
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值