ConstraintLayout的使用教程

该篇文章的主旨是帮助开发者了解ConstraintLayout的基本使用方法以及在日常开发项目中的使用场景的说明

ConstraintLayout官方文档

ConstraintLayout是一个ViewGroup,允许你灵活的指定子View的位置和大小(具体多灵活在下面的场景中进行说明),官方文档中说明ConstraintLayout的特性有以下几种:

  • Relative positioning - 相对位置
  • Margins - 边距
  • Centering positioning - 位置居中
  • Visibility behavior - 可见性行为
  • Dimension constraints - 尺寸限制
  • Chains - 链
  • Virtual Helpers objects - 虚拟帮助对象(Guideline)
  • Optimizer - 优化

以上几个特性部分有点抽象,官方文档中也对每一个特性都进行了详细的说明和举例,有意者可以单独去查阅,ConstraintLayout , 在下面的应用场景中也会穿插说明。对于开发者来说,主要了解使用场景和在项目中如何使用,用得多了就对该控件有了比较深入的了解。再看文档会更容易理解。毕竟文档是英文的。

使用说明

在没有ConstraintLayout之前我们写布局一般使用到的布局就是相对布局线性布局,相对布局中控件的位置都是基于另一个控件的位置,这个和ConstraintLayout有一丝相似之处,线性布局就是直接以瀑布流的形式进行布局。ConstraintLayout根据字面意思了解为约束布局,所以,所以在写布局文件的时候,需要对每一个控件进行约束 ,对每一个显示在约束布局中的内容进行约束,约束其大小,位置。下面介绍一下约束布局的相关属性和使用。

ConstraintLayout的基本属性

决定视图的大小和位置可以由View四个边来确定,left top right bottom, 所以约束布局可以通过对四个边的约束来达到实际布局效果,相关四个边的属性有,如:

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_constraintStart_toEndOf
app:layout_constraintStart_toStartOf
app:layout_constraintEnd_toStartOf
app:layout_constraintEnd_toEndOf
复制代码

应该根据这些属性的名称就能了解它们的作用,下面举例说明:比如实现一个登陆界面,两个文本框和一个按钮。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <EditText
        android:id="@+id/edt_username"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="25dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="25dp"
        android:hint="请输入用户名"
        android:inputType="text"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/edt_password"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dp"
        android:hint="请输入密码"
        android:inputType="textPassword"
        app:layout_constraintEnd_toEndOf="@id/edt_username"
        app:layout_constraintStart_toStartOf="@id/edt_username"
        app:layout_constraintTop_toBottomOf="@id/edt_username" />

    <Button
        android:id="@+id/btn_login"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="登 录"
        app:layout_constraintEnd_toEndOf="@id/edt_password"
        app:layout_constraintStart_toStartOf="@id/edt_password"
        app:layout_constraintTop_toBottomOf="@id/edt_password" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码

很简单的一个页面,如果用LinearLayout更快,但是ConstraintLayout本身就是为了解决复杂布局而生的,在日常开发中的需求可能会让你各种嵌套布局,但是ConstraintLayout基本上都是一个布局就可以ok,所以只有你了解后才知道使用有多得劲,现在简单的分析说明下上面的布局原理。

1.确定用户名EditText的位置和大小,从四个边来约束,首先约束top,使用top_toTopOf="parent"将用户名EditText的顶部和父布局的顶部关联起来,然后通过marginTop来增加边距,如果不设置top_toTopOf属性,marginTop属性是不起作用的,任何没有增加约束的设置margin属性都是不起作用的,上面的代码中我们将EditText的width设置为0dp,然后给左右两边分别增加了约束,约束到父布局的start和end,通过以上三个属性,就确定了该EditText的位置和大小。

2.确定了用户名EditText的位置之后,进行添加密码EditText,和上一个EditText类似,增加左右上三边的约束,不同的是top_toTopOf属性的值改为了edt_username,不在把约束添加到parent,而是添加到用户名的EditText,这样密码EditText就显示到用户名的下面了。登录同理

只需要记住,ConstraintLayout中的所有空间添加上 左上右下 四个边的约束,就能确定空间的位置(对应了开始说的 Relative positioning 和 Margins 两个特性) ,记住这个就掌握使用的一大半了

控件居中

想让控件居中也很简单,比如说上面的登录按钮,不想要那么大,可以将控件的width属性改成wrap_content,这样控件就直接居中了。

在给控件添加完约束之后,如果width或者height给的值为0,则控件的大小将完全按照约束的大小进行展示,如果设置了wrap_content,则控件会居中显示

基线对齐约束

该约束是针对文本相关控件添加的,比如要再添加一个注册按钮在登录的右侧

    <Button
        android:id="@+id/btn_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="登 录"
        app:layout_constraintEnd_toStartOf="@id/btn_sign_up"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toStartOf="@id/edt_password"
        app:layout_constraintTop_toBottomOf="@id/edt_password" />

    <Button
        android:id="@+id/btn_sign_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册"
        app:layout_constraintBaseline_toBaselineOf="@id/btn_login"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toEndOf="@id/btn_login"
        app:layout_constraintEnd_toEndOf="@id/edt_password"
        app:layout_constraintTop_toBottomOf="@id/edt_password" />
复制代码

在上面的注册控件中,增加了layout_constraintBaseline_toBaselineOf属性,依赖登录按钮,这样他们的绘制基线就在同一y轴上了,从而达到对齐的效果。

Chains

在上面的基线约束中,可能你会发现登录和注册的位置非常对称,这个就是chains约束,对于chains约束只说明两点,你就会轻松使用了。

  • 控件之间要相互依赖。

例如上面的登录和注册两个按钮,登录的右边距约束必须添加到注册的左边距上,即:登录的 end_ToStartOf="btn_sign_up",注册的 start_toEndOf="btn_login",如果是多个控件一样,一个控件的结束依赖到另一个的开始。这是水平chain , 垂直的桶里

  • 添加chain属性 待需要增加chain约束的控件都依赖完了之后,就需要给每个控件增加chain属性了,即:layout_constraintHorizontal_chainStyle 或者 layout_constraintVertical_chainStyle , 该属性可以有多个值,分别对应的效果借鉴官方文档的,如下:

Dimension constraints - 尺寸约束

layout_constraintDimensionRatio

尺寸约束的使用不多,但是这个属性很重要,在很多的场景中可以使用该约束,先对属性进行说明,应用场景后面再说。了解了作用,自然就能在实际开发中找到场景。比如说我们要实现一个ImageView的宽是高的2倍,可能有人想,我把宽固定了那高除以2不就出来了嘛,当然可以,但是有些场景,比如说宽是屏幕的宽度,match_parent呢,用尺寸约束就可以很轻松的达到效果。

  <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp" 
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintDimensionRatio="2:1"
        android:background="@color/colorAccent"
        />
复制代码

这样就比较轻松的实现了高是宽的2倍,在什么机型上都是。

百分比约束

layout_constraintHeight_percent

layout_constraintWidth_percent

分别对宽高进行百分比约束。

 <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHeight_percent="0.2"
        app:layout_constraintWidth_percent="0.5"
        android:background="@color/colorAccent"
        />
复制代码

百分比约束相对很实用,但是比较少用,很类似之前LinearLayout的weight权重。

Visibility behavior

可见性行为的属性包括:

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
复制代码

比如说上面的登录页面,如果程序中设置了用户名EditText设置了setVisible(false),那么密码EditText就会直接到顶部了,甚至造成布局错乱,为什么?应为密码EditText的左右约束添加到了用户名的EditText上,如果想让用户名EditText隐藏的时候密码EditText和top右边距,就可以给密码EditText加上goneMarginTop属性,为了防止因为控件隐藏造成布局错乱,在已知一些控件会隐藏的前提下,其他的控件不要左右边依赖可能会隐藏的视图,防止布局错乱 比如上面的为了防止用户名EditText隐藏造成密码EditText显示不了的问题,可以给密码EditText的左右依赖添加到父布局即可。

Guideline - Virtual Helpers objects

guideline也是一个控件,但是这个控件是只在约束布局中才能起作用的辅助控件 ,是帮助辅助布局的,比如说,我们添加一个GuideLine,将屏幕平分为两半,一个视图在左,一个在右。拿上面的登录注册两个按钮来说,上面的实现方式是增加了chain约束,也可以用GuideLine来实现。代码如下:

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <Button
        android:id="@+id/btn_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="登 录"
        app:layout_constraintEnd_toStartOf="@id/guideline"
        app:layout_constraintStart_toStartOf="@id/edt_password"
        app:layout_constraintTop_toBottomOf="@id/edt_password" />

    <Button
        android:id="@+id/btn_sign_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册"
        app:layout_constraintBaseline_toBaselineOf="@id/btn_login"
        app:layout_constraintEnd_toEndOf="@id/edt_password"
        app:layout_constraintStart_toEndOf="@id/guideline" />
复制代码

中间的虚线,即为增加的辅助GuideLine控件,该控件需要设置两个属性,第一是设置orientation属性,垂直或者水平,第二是百分比 layout_constraintGuide_percent,添加好辅助视图之后,其他控件就可以依赖于它进行布局。

以上几方面就是在日常开发中的基础使用相关介绍,掌握了这些基本上都能满足开发的需求,下面说下ConstraintLayout的使用场景

使用场景

  • 不带滚动的复杂布局

以前我们在实现布局的时候经常各种嵌套,现在不带滚动的布局,都可以只用一个父布局就可以解决,减少了布局的层级深度

  • 带滚动的复杂布局

在NestedScrollView中嵌套一个ConstraintLayout即可。

  • RecyclerView的item布局

以前item布局也是各种嵌套布局,有了ConstraintLayout之后发现真的是省事了很多,代码看起来也比较舒服

  • 尺寸约束和百分比的巧用

像有一些banner图的设计尺寸都是固定的,我们只需要宽度设置全屏,然后设置宽高比,就能适配所有屏幕,等等。。妙用很多,实际开发自己发掘。

总之如果在使用ConstraintLayout看了该内容哪里不对希望评论补充,或者不对的地方纠正我一下,如果是没有用过的,希望你赶紧用起来,省时省力

猜你喜欢

转载自juejin.im/post/5c447a1bf265da61141ce007