写点什么

深入分析 ConstraintLayout 的原理及应用场景,万字总结

用户头像
Android架构
关注
发布于: 1 小时前

当然不是。


ConstraintLayout 的约束关系,使它具备了另一个特点,那就是可以添加引导线来辅助布局,所有布局都可以在界面上通过拖动完成。如图。



点击 layout 布局后,选择图示右上角的 Design 按钮,即可拖动控件。


而 RelativeLayout 并不具备这一特点,这也让 ConstraintLayout 的布局调整更为方便、快捷。


如果此时非 ConstraintLayout 布局,在上图左方,右键点击最上部分的父容器,选择 Convert XXX to Constraintlayout 即可转化为约束布局。



  • RelativeLayout、ConstraintLayout 都可以通过 LayoutParams 动态新建布局,即在代码中控制控件尺寸和位置,而不只是在 xml 文件中设置静态的布局。但是,ConstraintLayout 引入了一个新的类,即 ConstraintSet,使它可以实现动画效果,对控件的控制能力也更加强大,这是 RelativeLayout 不具备的能力。

  • 性能上,ConstraintLayout 的渲染速度比 RelativeLayout 更快。


原因:


在布局上 RelativeLayout 内比 ConstraintLayout 多了一层 ViewGroup,如这样一种情况,屏幕分成两半,左半部分只有一个 button,右半部分从上到下有多个 button,左边的 button 需要居中对齐右边,那么便需要将右半部分的多个 button 用一个 viewgroup 包裹起来。这样便多了一层嵌套,渲染时间增加。


值得注意的是,LinearLayout 的渲染速度也快于 RelativeLayout,原因:因为 RelativeLayout 通过在水平、垂直方向对另一控件的依赖,来计算自身的位置,因此会执行两遍 measure,而 LinearLayout 只需测量一次。ConstraintLayout 是 RelativeLayout 的升级版,LinearLayout 的渲染速度同样快于 ConstraintLayout。


因此对于层次不深的简单布局,优先使用 LinearLayout。


这里可能会有人有疑惑,那层次深与不深又怎么划分呢?三层、四层算深还是五层、六层?


个人的想法是,如果布局仅有一层,不需嵌套,直接使用 LinearLayout;如果嵌套多于一层,而根布局需要采用 RelativeLayout 或 ConstraintLayout 时,可以直接采用 ConstraintLayout。

ConstraintLayout 使用条件与场景

使用条件

  • ConstraintLayout 布局内的控件必须有水平方向和垂直方向的约束,来表示与父布、兄弟控件的连接或对齐。

  • 水平方向上,start 和 end 为一组。

  • 垂直方向上,top 和 bottom 为一组。


约束如下。


//与父布局底部对齐(parent 可改为其他控件 ID,即与其他控件底部对齐,下同)app:layout_constraintBottom_toBottomOf="parent"


//与父布局顶部对齐 app:layout_constraintTop_toTopOf="parent"


//与父布局左端对齐 app:layout_constraintStart_toStartOf="parent"


//与父布局右端对齐 app:layout_constraintEnd_toEndOf="parent"


//在父布局的上方(看属性最右边的元素,即 Top,下同)app:layout_constraintBottom_toTopOf="parent"


//在父布局的下方 app:layout_constraintTop_toBottomOf="parent"


//在父布局的右方 app:layout_constraintStart_toEndOf="parent"


//在父布局的左方 app:layout_constraintEnd_toStartOf="parent"

使用前导包

  1. 在顶级 build.gradle 文件中


repositories {google()}


  1. 模块级 build.gradle


// 尽可能地下载最新版本,如果不确定最新版本号,可以先写入 1.0.0,系统会标注提醒最新版本号.dependencies {implementation "androidx.constraintlayout:constraintlayout:2.0.4"}

使用场景

  • 场景 a:A 控件与“222”控件居中对齐,且“222”控件在 A 控件下方。如图(即基于某控件的一边,居中对齐)



代码实现如下:


<?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"tools:context=".MainActivity">


<TextViewandroid:id="@+id/tv1"android:layout_width="100dp"android:layout_height="40dp"android:gravity="center"android:text="A"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />


//因为要位于下方,所以使用 layout_constraintTop_toBottomOf 属性;//同时左右两边要基于另一控件对齐(因为要居中)<TextViewandroid:id="@+id/tv2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="222"app:layout_constraintStart_toStartOf="@id/tv1"app:layout_constraintEnd_toEndOf="@id/tv1"app:layout_constraintTop_toBottomOf="@id/tv1"/>


</androidx.constraintlayout.widget.ConstraintLayout>


  1. 居中用法引申:同一维度(上下或左右)的两个方向同时出现,且相对于父布局对齐。

  2. 非居中用法引申:若不居中对齐,而是基于某一边对齐,只需去掉同一个维度的某一个方向。例如,上方代码中,去掉 app:layout_constraintEnd_toEndOf="@id/tv1", 即实现 A 与“222”控件左方对齐,且 A 在“222”控件上方。


  • 场景 2:六个控件在布局中以三行三列形式分布,且行均分布局高度,列均分布局宽度。如图。



核心实现流程如下:


  1. 每一个相对的控件,都要写出相约束的属性(比如 layout_constraintEnd_toStartOf;layout_constraintStart_toEndOf)。

  2. 每个控件四个方向的约束位置都要写出来。

  3. 每一个横向或竖向位置的两端,必须与 parent 相对。


// 横向:app:layout_constraintStart_toStartOf="parent"app:layout_constraintEnd_toEndOf="parent";


// 竖向:app:layout_constraintTop_toTopOf="parent";app:layout_constraintBottom_toBottomOf="parent";


  1. 利用权重实现均分(weight 属性)

  2. 均分时,长或宽都必须为 0。


代码如下所示。


<?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"tools:cont


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ext=".MainActivity">


/*核心代码*/<Buttonandroid:id="@+id/btn1"android:layout_width="0dp"android:layout_height="0dp"android:text="btn1"app:layout_constraintBottom_toTopOf="@id/btn4"app:layout_constraintEnd_toStartOf="@+id/btn2"app:layout_constraintHorizontal_weight="1"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_weight="1" />


<Buttonandroid:id="@+id/btn2"android:layout_width="0dp"android:layout_height="0dp"android:text="btn2"app:layout_constraintBottom_toTopOf="@id/btn5"app:layout_constraintEnd_toEndOf="@id/btn3"app:layout_constraintHorizontal_weight="1"app:layout_constraintStart_toEndOf="@+id/btn1"app:layout_constraintTop_toTopOf="@+id/btn1"app:layout_constraintVertical_weight="1" />


<Buttonandroid:id="@+id/btn3"android:layout_width="0dp"android:layout_height="0dp"android:text="btn3"app:layout_constraintBottom_toTopOf="@id/btn6"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_weight="1"app:layout_constraintStart_toEndOf="@+id/btn2"app:layout_constraintTop_toTopOf="@+id/btn2"app:layout_constraintVertical_weight="1" />

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
深入分析ConstraintLayout的原理及应用场景,万字总结