ConstraintLayout基础介绍

2023-05-16

自去年Google I/O 大会发布ConstraintLayout至今,已有一年多的时间,但是并没有普及开来,了解过ConstraintLayout布局的人知道,它的性能的确提升了不少。在前不久,Google 开发者博客发布了一篇文章[Understanding the performance benefits of ConstraintLayout](https://android-developers.googleblog.com/2017/08/understanding-performance-benefits-of.html)(中文地址)详细分析ConstraintLayout性能的优势,感兴趣的朋友可以去看看。

当然自己之前也没有认识到ConstraintLayout布局的性能优势,所以从这篇文章开始由浅入深详细介绍ConstraintLayout的属性及使用,也让自己对ConstraintLayout也有一个更全面的认识,今天的这篇文章主要介绍布局的一些属性,学习地址是Google文档。

配置

在使用ConstraintLayout之前我们需要在我们app下的gradle文件添加ConstraintLayout依赖,截止到目前ConstraintLayout的最新版本是1.0.2.

dependencies {
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
}

Relative positioning

相对定位的效果和RelativeLayout布局有异曲同工之处,只不过要比RelativeLayout强大。约束能允许我们指定一个控件相对于另一个控件的位置,通过一些属性我们可以对组件进行水平或者垂直排列。例如当我们使用含有Left, Right, Start 或者End关键词词属性进行定位时即是对组件进行水平方向排列,同理 top, bottom 和 text baseline(文字的基线位置)就是垂直方向排列。具体相对定位的一些属性组合如下

  • 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

对于上面这些属性的值有两种,一种就是同层级组件ID,还有就是parent,当值为parent时即是相对于父布局进行定位。

<?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">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="textView1" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="textView2"
        app:layout_constraintLeft_toRightOf="@+id/textView1" />
</android.support.constraint.ConstraintLayout>

例如上面的布局,我们使用app:layout_constraintLeft_toRightOf=”@+id/textView1”将textView2的左边和textView1的右边对齐,效果图

image.png

那么当textView2属性设置为

    app:layout_constraintTop_toBottomOf="@+id/textView1"
    app:layout_constraintLeft_toRightOf="@+id/textView1"

效果图:
image.png

当textView1设置属性 app:layout_constraintRight_toLeftOf=”parent”
textView2设置 app:layout_constraintLeft_toLeftOf=”parent”时,

效果图:
image.png

Margins

对于margin值我们都不陌生,因为我们经常使用,有以下几种

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

需要注意的是此margin只对于设置了约束的地方起作用,如下布局

<?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">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:text="textView1" />
</android.support.constraint.ConstraintLayout>

我们只设置了TextView的左边和父布局左边约束,当我们设置了左边和上边的margin值都为10时,发现只有左边的边距生效,而上边的变化没有发生作用,这也就验证了边距只对有约束行为的地方起作用。

除了我们常用的margin设置属性外,ConstraintLayout 还提供了一些特有的margin设置。先看下面布局

<?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">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="textView1"
        app:layout_constraintLeft_toLeftOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="textView2"
        app:layout_constraintLeft_toRightOf="@+id/textView1" />
</android.support.constraint.ConstraintLayout>

上面textview2在textview1的右边,那么当我们由于某种需求将textview1设置了 View.GONE隐藏该控件,那么此时textview2将跑到位置将显示在左上角,如果我们在隐藏textview时而保持textview2位置不变。在之前的应用中能稍微比较麻烦一点,但是ConstraintLayout 给我们提供了layout_goneMargin**类的属性,该属性是表示约束隐藏时的margin值。例如上面的textView2我们增加app:layout_goneMarginLeft=”100dp”属性就可以保持当约束textView1隐藏时而保持textview2位置不变。

需要注意的一点是如果某个约束设置了View.GONE,相当于这个组件宽和高为0,约束布局中相当于一个点,其他设置的约束依然有效。

Centering positioning and bias

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="textView1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

如果约束布局中我们添加textview并设左边和父布局左边,右边和父布局右边对齐,并设置宽度100dp,那么此时效果是怎样的呢。我们发现textview居中显示了,这就是约束布局的居中定位。
其实我们可以理解为父布局对textview左边和右边都有一个拉力,由于默认这个力大小相同就到显示到中间位置。

image.png

在上面由于两个相反的约束,而使组件居中,在协同布局中还提供了bias,通过属性layout_constraintHorizontal_bias或者layout_constraintVertical_bias设置组件偏向水平或者垂直的某一测,,默认情况下该值是0.5(50%).例如我们设置textview属性

        app:layout_constraintHorizontal_bias="0.3"

此时组件偏向左边
image.png

Dimensions constraints

当我们的协调布局的子组件设置wrap_content时,我们可以通过android:minWidth或者android:minHeight 属性设置最小宽度或者高度的约束。minWidth/minHeight只有宽度或者高度为wrap_content才有作用。

对于android:layout_height /android:layout_width属性,它的值只有三种情况
- 使用指定的大小或者指定大小的引用,如100dp
- WRAP_CONTENT,此时根据内容自己计算大小
- 0dp,该值相当于MATCH_CONSTRAINT。

需要注意的是在约束布局中MATCH_PARENT 属性值不在支持,例如在上面的TextView我们设置layout_width分别是100dp,0dp,0dp(marginLeft :20dp)大致效果如图a,b,c

image.png

Ratio

比例约束可以约束我们控件的宽高比,例如下面示例

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="textView1"
        app:layout_constraintDimensionRatio="2:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

设置宽度为100dp,高度为0dp,此时设置了宽高比是2:1,则宽度会自动约束调整为50dp。
如果我们将上面的宽和高度调换,宽为0dp,高100dp,此时最终宽度为200,高度100(宽:高=2:1)

在上面介绍的的宽高比约束是单维度的,那么如果我们的宽和高都有约束,都设置为0dp,在这种情况下,系统会使用满足所有约束条件和比率的最大尺寸。当然我们也可以在比例值前面加 W 或者 H 来分别约束宽度或者高度,如H,2:1。

Chains

链是一种特殊的约束它能让多个该链连接的 多个Views 平分剩余空间位置
如下我们创建一个水平链

<?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">

    <TextView
        android:id="@+id/A"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:background="@color/btnnormal"
        android:gravity="center"
        android:text="A"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/B" />

    <TextView
        android:id="@+id/B"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="B"
        app:layout_constraintLeft_toRightOf="@+id/A"
        app:layout_constraintRight_toLeftOf="@+id/C" />

    <TextView
        android:id="@+id/C"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:background="@color/btnnormal"
        android:gravity="center"
        android:text="C"
        app:layout_constraintLeft_toRightOf="@+id/B"
        app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>

上面代码的效果图如下,A和C相对于父组件的左边和右边有一个约束,A和B,B和C之间两两相互约束,我们还需要知道的是对我们称链的第一个元素组件为链头。如下图A就是该链的链头
image.png

链的模式

对于链头我们可以通过属性layout_constraintHorizontal_chainStyle(layout_constraintVertical_chainStyle)设置,该属性有三个值,spread ,spread_inside ,packed
- CHAIN_SPREAD
默认情况下该属性默认值是spread 。它的间隙将平分剩余空间,如上图所示
- CHAIN_SPREAD_INSIDE
spread_inside值会把两边最边缘的两个 View 靠边显示,然后让剩余的 Views 在剩余的空间内平分间隙。当面设置spread_inside时效果图如下

image.png

  • CHAIN_PACKED
    还有一种值是packed ,它表示将view之间紧挨着显示,并且全体居中显示,设置该模式后效果图如下

image.png
除此之外,我们可以通过设置layout_constraintHorizontal_bias属性来调整整体的位置。默认情况居中,也就是该值为0.5,例如我们将该值设置0.3,则实现效果如下

image.png
- Weighted chain
在官方文档中还介绍了一种模式是权重模式,在CHAIN_SPREAD 模式中,如果我们设置控件的宽或者高设置MATCH_CONSTRAINT即0dp,它们将按权重平分占满父控件的宽或者高,对于权重的设置是属性和我们线性布局设置权重达到一样的效果,例如在上面的三个TextView,我们设置宽度都为0dp,并设置链样式为spread(或spread_inside),此时效果 图如下

image.png
如果我们给A和C设置下面属性

        app:layout_constraintHorizontal_weight="1"

给B设置属性

        app:layout_constraintHorizontal_weight="2"

那么此时A,B,C的宽度为1:2:1比例占满父组件宽度。设置权重时链样式不能设置为packed (设置后宽度会收缩为0)

参照线Guideline

Guideline用于辅助我们对View进行定位,以及设置约束,它不会再真正的显示,只是起到辅助作用,常用属性如下

  • android:orientation
    该属性可以指定辅助线是垂直还是水平线,它有两个值即vertical,horizontal,
  • layout_constraintGuide_begin/layout_constraintGuide_end
    用来设置对齐父组件的 start 或者end边缘的距离,
  • layout_constraintGuide_percent
    该值是0.0到1.0之间,用来设置辅助线在父布局的位置,例如设置0.5,就相当于在父视图宽度的中间50%。
    <android.support.constraint.Guideline
        android:id="@+id/guideline_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />

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

    <TextView
        android:id="@+id/tvguide"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/red"
        android:gravity="center"
        android:text="Guide"
        app:layout_constraintBottom_toTopOf="@+id/guideline_h"
        app:layout_constraintLeft_toLeftOf="@+id/guideline_v" />

在上面我们在约束布局中创建两个辅助线,分别是垂直和水平的辅助线,并将textView的下面和水平辅助线的上面对齐,将TextView的左边和垂直辅助线左边对齐。这样我们可以使用辅助线任意控制View的约束位置。

image.png
好了今天ConstraintLayout的基础知识就介绍到这里了,下一篇文章将介绍ConstraintLayout布局中Behavior的相关知识,如文中有错误欢迎指出。Hava a wonderful day。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ConstraintLayout基础介绍 的相关文章

随机推荐

  • Ubuntu12.04的汉化

    博主装上了Ubuntu12 04后进入系统才发现是英文版 xff0c 看着挺费劲的 xff0c 所以需要汉化一下 本文适用于ubuntu 12 04英文版的系统 1 进入ubuntu系统 xff0c 在顶部齿状标志找到system 2 在p
  • freertos优化版printf、sprintf、snprintf

    优化版printf sprintf snprintf printf stdarg c 当调用标准 C 库函数时 xff0c 栈空间使用量可能会急剧上升 xff0c 特别是 IO 与字符串处理函数 xff0c 比如 sprintf 在 Fre
  • 分享一下我参加开发者大会以来自己的总结(仅供参考)

    手机游戏设计 1选材类型符合移动平台特性 2剧情背景知名度高 3选材定义自己的用户 xff0c 用户觉得游戏的玩法 游戏设计法则 xff08 无需全部实现 xff0c 根据自己游戏类型找和适合法则结合 xff09 法则 1 xff1a 富有
  • 时钟周期、机器周期、指令周期的概念及三者之间的关系;定时器及计数器

    时钟周期 时钟周期也称为振荡周期 xff0c 定义为时钟脉冲的倒数 可以这样来理解 xff0c 时钟周期就是单片机外接晶振的倒数 xff0c 例如12M的晶振 xff0c 它的时间周期就是1 12 us xff0c 是计算机中最基本的 最小
  • 自旋锁-原理

    跟互斥锁一样 xff0c 一个执行单元要想访问被自旋锁保护的共享资源 xff0c 必须先得到锁 xff0c 在访问完共享资源后 xff0c 必须释放锁 如果在获取自旋锁时 xff0c 没有任何执行单元保持该锁 xff0c 那么将立即得到锁
  • openvslam------slam解读系列

    是什么 openvslam是日本先进工业科技研究 xff08 National Institute of Advanced Industrial Science and Technology xff09 所于2019年5月20日开源的视觉S
  • Hadoop编程学习1--WordCount

    span class hljs keyword package span org apache hadoop examples span class hljs keyword import span java io IOException
  • p2p传输实时视频流

    HYP2P是好游科技开发的p2p sdk xff0c 利用nat穿透的原理实现p2p打洞 xff0c 主要用于实时音视频的传输 使用时可以配置成tcp模式或udp模式 xff0c tcp模式会自动帮您解决丢包 乱序 重传问题 中转模式则是基
  • 笑谈Android图表------MPAndroidChart

    MPAndroidChart是一款基于Android的开源图表库 xff0c MPAndroidChart不仅可以在Android设备上绘制各种统计图表 xff0c 而且可以对图表进行拖动和缩放操作 xff0c 应用起来非常灵活 MPAnd
  • 详谈高大上的图片加载框架Glide -应用篇

    在Android设备上 xff0c 加载网络图片一直是一个头疼的问题 xff0c 因为Android设备种类繁多 xff08 当然最主要的是配置 xff09 xff0c 处理的稍不周到轻则应用卡顿 xff0c 严重者就会出现OOM的 xff
  • 微信小程序开发环境搭建

    微信小程序可谓是今天最火的一个名词了 xff0c 一经出现真是轰炸了整个开发人员 xff0c 当然很多App开发人员有了一个担心 xff0c 微信小程序的到来会不会给移动端App带来一个寒冬 xff0c 身为一个Android开发者我是不相
  • 实现APP定位功能

    源码传送门 若你不小心点击进入GitHub了捎带给个star 前言 最近更新项目中用的百度定位SDK时遇见了一个奇葩的问题 当升级SDK后百度定位一直返回505 通过百度定位官网查看该码表示AK非法或者不存在 很纠结 于是自己又写了一个de
  • Linux系统命令行创建新文件

    linux命令行创建文件 方法有许多 xff0c 下面简单介绍一下 方法1 使用cat命令 cat span class token operator gt span sample1 span class token punctuation
  • Java利器之UML类图详解

    前言 UML xff08 Unified Modeling Language xff09 中文统一建模语言 xff0c 是一种开放的方法 xff0c 用于说明 可视化 构建和编写一个正在开发的 面向对象的 软件密集系统的制品的开放方法 UM
  • 从零开始学习Linux部署Java web项目

    前言 最近越来越发现需要学习的东西太多了 xff0c 前几天公司服务器出现问题 xff0c 需要对服务器硬件进行维护 xff0c 当然服务器上的服务需要部署到另一个服务器上 这对于我来说是很陌生的 xff0c 虽然这件工作没有让我去做 xf
  • 致敬我奋起直追的2016

    前言 其实当用奋起直追这个词语形容我的2016时 xff0c 自己一度怀疑是不是配得上这个词语 虽然2016成长了不少 xff0c 但是依然没有达到我想要的效果 在学习过程中不断出现越学越倒退的感觉 还偶尔会出现一些恐惧感 不过庆幸的是 x
  • 微信小程序分页加载

    分页加载功能大家遇到的应该会经常遇到 xff0c 应用场景也很多 xff0c 例如微博 xff0c QQ xff0c 微信朋友圈以及新闻类应用 xff0c 都会有分页加载的功能 xff0c 这不仅节省了我们用户的流量 xff0c 还提升了用
  • ReactNative ViewPageAndroid组件详解

    源码传送门 在我们开发Android的时候 xff0c ViewPage这个控件的使用频率还是很高的 xff0c 最简单的就是制作引导页 xff0c 应用程序的主界面等 xff0c 在ReactNative开发中实现该功能的组件是ViewP
  • Android自定义数字键盘

    好久没有写Android的文章了 xff0c 有两三个月多了吧 xff0c 刚开始搞微信小程序 xff0c 后来又开搞ReactNative 现在又兴奋的开搞AI机器学习的东西 xff0c 感觉挺有意思的 xff0c 不过AI与其它的东西相
  • ConstraintLayout基础介绍

    自去年Google I O 大会发布ConstraintLayout至今 xff0c 已有一年多的时间 xff0c 但是并没有普及开来 xff0c 了解过ConstraintLayout布局的人知道 xff0c 它的性能的确提升了不少 在前