Android ConstraintLayout使用攻略

news2025/1/9 23:33:24

原文链接 Android ConstraintLayout使用攻略

ConstraintLayout是新一代的布局,它汲取了众家之长,把布局的概念进行了大统一,灵活且强大,基本上可以干掉以前所有的常用布局(LinearLayout, RelativeLayout和FrameLayout)。自从Android Studio 2.3(大约在2017年)后,它就变成了Android Studio的默认模板的布局控件,可以看出谷歌对它的钟爱程度。今天就来学习一下如何使用这个新布局神器。

简述

ConstraintLayout与RelativeLayout有些类似,是一个布局管理器(ViewGroup),但要强大许多,它可以以各种方式排列子View,以及按比例伸缩。最重要的改变就是它对于『Drag and drop』拖拽式制作GUI页面支持的相当的好。当然了这个取决于个人喜好,很多人仍然喜欢用写代码的方式直接去写xml文件,包括我在内。拖拽式虽然直观,但是不方便精准控制,对于一般性的布局来说尚可,但稍复杂了后,以及有了一些可滑动的view时,就不是那么的方便了。对于喜欢拖拽的同学可以查看官方的一个教程,以及郭大婶的一篇文章,这两篇专注于拖拽式,且讲的都比较详细。

添加依赖

因为ConstraintLayout并不是在标准的SDK中,而是被放在了support SDK中,现在统一叫androidx了,所以要单独添加依赖:

     dependencies {
          implementation 'com.android.support.constraint:constraint-layout:2.1.0'
     }

概念与术语

ContraintLayout中把一切有关布局的参数都称之为Constraint(约束),长和宽,对齐,居中,margin和padding都是constraint。布局中的属性均以"layout_constraint"为前缀。
约束(Constrain)的意思是指用另外一个View(包括父布局即ContraintLayout)对当前View的某一布局参数施加影响。具体的影响叫做Constraint,另外一个View称作约束对象(Constraining Object),当前View称作被约束对象(Constrainted Object)。

在这里插入图片描述

     <Button android:id="@+id/buttonA" ... />
     <Button android:id="@+id/buttonB" ...
          app:layout_constraintLeft_toRightOf="@id/buttonA" />

排列方式

对子View的排列方式是一个ViewGroup的最基础的功能,它也体现了不同的布局管理器的作用,如线性布局(LinearLayout)是以水平或者垂直方向平铺方式来排列子View的。ConstraintLayout是以类似RelativeLayout的方式,需要针对每个子View指定如何排列。

在这里插入图片描述

基础排列方式

最为基础的排列方式就是针对每个子View,指定它相对于另外一个View或者父布局(也就是ConstraintLayout本身)的相对位置,从而确定该View的具体方位。具体就是[left, top, right, bottom]四个关键的排列元素相对于另外一个View或者父布局的位置关系。

如,layout_constraintLeft_toLeftOf=“parent”,这就是左边与父布局左边对齐;layout_constraintTop_toBottomOf=“id/header”,这是把这个View放在id为header的下面。以此类推,因为与RelativeLayout的布局参数比较类似,就不细说了,详情可参阅文档。

还有一个非常实用的Constraint叫做baseline,它是专门针对TextView的,baseline也即文本的基线,可以简单理解为文字的底部,当有两个TextiView不一样大,文字大小也不一样时,却需要对齐文本,这个属于就相当的有用。

在这里插入图片描述

    <TextView android:id="@+id/TextView1"/>

    <TextView
        android:id="@+id/TextView2"
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_constraintBaseline_toBaselineOf="@+id/TextView1"/>

margin

常规使用与其他布局是一样的,通过layout_margin[Start,End,Left,Right,Bottom,Top]来指定与约束对象之间的margin,这个不细说了。

需要说一下,ConstraintLayout有一个goneMargin,可以用于当一个约束对象的Visibility被设置为GONE时,使用。用layout_goneMargin[Start,End,Left,Top,Right,Bottom]来设置。

比如A约束B,B在A的右边,它俩挨着,但如果A的Visibility设置为GONE时,正常情况下B就会挨到原来A的左边了,跑到了左边界上,这时可能就会变得比较丑了,如果使用margin,比如在A和B中间加一个margin,可以解决问题,但是也会影响当A可见的时候。而用goneMargin就可以完美的解决此种场景。layout_goneMarginStart=“10dip”,那么这个margin只有当约束对象A的Visibility被置为GONE时,才会生效,这时B虽然跑到了左边界上,但是还有margin,就不会那么丑了。(其实goneMargin应用的场景也比较有限,前面说的case,也可以用A和B的父布局的leftPadding来解决)

在这里插入图片描述

相当骚气的环状排列方式

除了常规的行列式排列以外,这货还非常骚气的可以环状排列,以约束对象为圆心,通过角度和半径来约束位置:

  • layout_constraintCircle 用以指定作为圆心的约束对象(其他view的id)
  • layout_constraintCircleRadius 被约束对象与圆心的距离
  • layout_constraintCircleAngle 被约束对象与横轴的角度(0~360度之间)

在这里插入图片描述

  <Button android:id="@+id/buttonA" ... />
  <Button android:id="@+id/buttonB" ...
      app:layout_constraintCircle="@+id/buttonA"
      app:layout_constraintCircleRadius="100dp"
      app:layout_constraintCircleAngle="45" />

环状排列实例

环状排列虽然骚气,但是现实中似乎应用场景不多。

居中与对齐

对齐不是大问题,前面讲的如何排列其实就是对齐,选定一个约束对象后,其他对象都受其约束,就自然对齐了。

比较常见的问题,以及大部分时候比较麻烦的是居中,平衡与中庸中符合绝大多数审美的,因此布局时,绝大多数情况下都是需要居中的。居中的实现的方式就是两边都约束于父布局(也即ConstraintLayout),如:

在这里插入图片描述

         <androidx.constraintlayout.widget.ConstraintLayout ...>
             <Button android:id="@+id/button" ...
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent"/>
         </>

居中,其实就是两边的约束边距各占空余空间的50%,扩展开来,想要实现不完全居中,两边边距呈一定比例关系,也是可以办到的。比如说黄金比例0.618就比居中好看,这也好办:
在这里插入图片描述

       <androidx.constraintlayout.widget.ConstraintLayout ...>
             <Button android:id="@+id/button" ...
                 app:layout_constraintHorizontal_bias="0.382"
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent"/>
      </>

这个比例控制叫bias,可以有Horizontal和Vertical两个方向。

尺寸

尺寸也就是针对子View的宽与高的约束,其实大部分时候一些具体的子View的宽与高要么指定大小,要么是WRAP_CONTENT的,但有些时候可能就是需要更加的灵活一些,这时就可以考虑用ConstraintLayout里面的一些特性。宽与高设置为固定大小或者WRAP_CONTENT时与其他ViewGroup是一样的,不用多说,要想特别一点的就是设置为『0dip』或者MATCH_CONSTRAINT时,就会用其他约束来决定该View的宽或者高。后面重点讨论有约束的情况。

默认行为

如果子View的宽或者高设置为了MATCH_CONSTRAINT(或者『0dip』)时,默认的行为是它会占满剩余的可用空间。

Max与Min

还可以加上最大最小的限制:

  • layout_constraintWidth_min and layout_constraintHeight_min : will set the minimum size for this dimension
  • layout_constraintWidth_max and layout_constraintHeight_max : will set the maximum size for this dimension
  • layout_constraintWidth_percent and layout_constraintHeight_percent : will set the size of this dimension as a percentage of the parent

按约束对象的比例来设置(Percent)

前面的默认行为或者最大最小还算不上啥,其他ViewGroup也有类似参数。最为变态与强大的是可以按约束对象的比例来作为此View的宽或者高:

  • The dimension should be set to MATCH_CONSTRAINT (0dp)
  • The default should be set to percent app:layout_constraintWidth_default=“percent” or app:layout_constraintHeight_default=“percent”
  • Then set the layout_constraintWidth_percent or layout_constraintHeight_percent attributes to a value between 0 and 1

自身宽高比(Ratio)

这个是最变态的约束方式,可以设置一个自身的宽高比,以确定子View的尺寸,当然了具体的宽或者高还要以其他约束方式确定具体尺寸,然后再按照设置的宽高比对另外一个进行约束。比如,实现一个方形的按扭,宽是其自身要求的宽度值(WRAP_CONTENT),设置的宽高比是1:1,所以高度也会跟宽度一样,就是一个方形的按扭了:

        <Button android:layout_width="wrap_content"
                   android:layout_height="0dp"
                   app:layout_constraintDimensionRatio="1:1" />

高级特性

前面讲的是一些基础使用方式,但是这货远不止这些,还有一些非常强大的功能,下面简单介绍两个。

链(Chains)

在某一个方向上(横着或者竖着)有着相互约束的一组子View,会被视为一个链,第一个称作头部(Head),可以应用一些样式以对整个链内的子View都产生影响。
在这里插入图片描述

这里的相互约束的意思是,比如有上面A,B,C三个子View,那么它们要相互约束,也即:

  <ConstraintLayout>
      <A layout_constraintLeft_toLeftOf="parent"
           layout_constraintRight_toRightOf="B" />
      <B layout_constraintLeft_toLeftOf="A"
           layout_constraintRight_toRightOf="C" />
      <C layout_constraintLeft_toLeftOf="B"
           layout_constraintRight_toRightOf="parent" />
  </ConstraintLayout>

就可以,对头部子View A进行样式(Chain style),通过layout_constraintHorizontal_chainStyle来设置:

  • CHAIN_SPREAD – the elements will be spread out (default style)
  • Weighted chain – in CHAIN_SPREAD mode, if some widgets are set to MATCH_CONSTRAINT, they will split the available space
  • CHAIN_SPREAD_INSIDE – similar, but the endpoints of the chain will not be spread out
  • CHAIN_PACKED – the elements of the chain will be packed together. The horizontal or vertical bias attribute of the child will then affect the positioning of the packed elements

在这里插入图片描述

链中的权重(Weighted chains)

默认情况下,子View会均分并占满可用的空间。可以用权重来按比例分配,给子View加上layout_constraintHorizontal_weight后,就会按比例分配,这个与LinearLayout的layoutWeight用法是一样的。

组(Groups)

为了View的渲染性能,各路大神告诉我们要尽可能的让布局扁平化,但是,如果太扁平了,全都放在一个ViewGroup下面,就会混乱,特别是像RelativeLayout和ConstraintLayout,子View的排列方式会产生相互依赖,会有牵一发动全身的情况出现。为了避免这种情况,就需要对子View进行分组,对页面进行区域划分,把紧密相关的视为一个组。以往,会用一个子ViewGroup把一个组包起来,虽然会加深View的层次,但这样能避免牵一发动全身。

而对于ConstraintLayout来说,有更先进的方式了,它有一个类叫Group,就是专门用来干这件事儿的,但Group对象并不是一个真的子View,这里的意思是它并不会在View tree中进行渲染,它是专门用于管理属于它的子View的,比如方便对整个组进行Visibility的设置。

神器要如何使用

前面的介绍就差不多了,ConstraintLayout还是相当的强大的,如有可能还是尽可能的多用它吧。它的实现上面确实挺复杂的,毕竟功能比较强大,但它的效率并不差。对于常用的几大布局都可以直接用它来替代。

当线性布局使用(as LinearLayout)

线性布局最大的优势就在于可以用weight的方式来按比例排放,而这个用前面提到的Chain就可以完美的解决。所以,LinearLayout可以完全放弃。

当层叠布局使用(as FrameLayout)

FrameLayout的全用场景一般是作为整个应用的根布局,特别是HomeActivity+Fragment这种架构。从纯的功能角度来讲,ConstraintLayout可以完全实现FrameLayout的所有功能,所以,FrameLayout也可以放弃。

但从简单方便角度来讲,假如是HomeActivity的根布局,子View都是MATCH_PARENT的Fragement的话,也没有必要换成ConstraintLayout,这种场景FrameLayout完全够用,而且非常适合它。换成ConstraintLayout反倒有些浪费,有些杀鸡用牛刀。

当相对布局使用(as RelativeLayout)

从前面的讲述可以看出,ConstraintLayout几乎就是RelativeLayout的加强版。所以,凡是用到RelativeLayout的地方都应该换成ConstaintLayout

参考资料

  • Build a Responsive UI with ConstraintLayout
  • ConstraintLayout
  • 约束布局ConstraintLayout看这一篇就够了
  • Use ConstraintLayout to design your Android views
  • ConstraintLayout Tutorial for Android: Complex Layouts
  • Constraint Layout Tutorial With Example In Android Studio
  • Android新特性介绍,ConstraintLayout完全解析

原创不易,打赏点赞在看收藏分享 总要有一个吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

94.qt qml-分页Table表格组件

在我们之前学习了87.qt qml-分页组件控件(支持设置任意折叠页数等)_qt分页控件_诺谦的博客-CSDN博客 然后我们又学习了Table实现,所以本章实现一个分页Table表格组件,配合分页控件, 模拟请求服务器数据来实现数据分解效果,因为一般使用分页的时候,一般都是分页请求,避免数…

Flutter的开发环境搭建-图解

前言&#xff1a;Flutter作为一个移动应用开发框架&#xff0c;具有许多优点和一些局限性。最大的优点就是-跨平台开发&#xff1a;Flutter可以在iOS和Android等多个平台上进行跨平台开发&#xff0c;使用一套代码编写应用程序&#xff0c;节省开发时间和成本。 Flutter可以编…

python将大文件拆分为多个小文件

如上图&#xff0c;目前采用单行不停写入的方式&#xff0c;这里是读了两次文件&#xff0c;第一次读取文件是为了获取总行数&#xff0c;第二次读取是取数据内容。 如果只读取一次文件&#xff0c;则会对内存有一定的要求&#xff0c;会需要在第一次读取数据的时候就将文件内…

ONNX Runtime 加速深度学习(C++ 、python)详细介绍

ONNX Runtime 加速深度学习(C 、python)详细介绍 本文在 https://blog.csdn.net/u013250861/article/details/127829944 基础上进行了更改&#xff0c;感谢原作&#xff01; ONNXRuntime(Open Neural Network Exchange)是微软推出的一款针对ONNX模型格式的推理框架&#xff0c…

Redis常用数据类型和使用场景

Redis目前支持5种数据类型&#xff0c;分别是&#xff1a; String&#xff08;字符串&#xff09; List&#xff08;列表&#xff09; Hash&#xff08;字典&#xff09; Set&#xff08;集合&#xff09; Sorted Set&#xff08;有序集合&#xff09; 下面就分别介绍这五…

Qt Core学习日记——第六天QMetaMethod

Qt子类会将每一个函数封装成QMetaMethod存储在对应的QMetaObject中&#xff0c;包括信号、槽函数、普通函数、构造函数、析构函数 函数解析 QMetaMethod::methodSignature 获取方法的签名 比如函数slot2&#xff0c;对应签名是“slot2(int*)” QMetaMethod::name 方法名称。…

13.2.3 【Linux】新增与移除群组

基本上&#xff0c;群组的内容都与这两个文件有关&#xff1a;/etc/group, /etc/gshadow。 群组的内容其实很简单&#xff0c;都是上面两个文件的新增、修改与移除而已。 groupadd 为了让使用者的 UID/GID 成对&#xff0c;建议新建的与使用者私有群组无关的其他群组时&#x…

RabbitMQ入门,springboot整合RabbitMQ

周末的两天没有写文章&#xff0c;因为项目分离出来了一个权限管理平台&#xff0c;花了一点时间整理项目&#xff0c;同时完成了一些功能的开发。 今天这篇文章介绍一下RabbitMQ这个消息中间件&#xff0c;以及通过springboot整合RabbitMQ。 目录 一、初步了解RabbitMQ 二、…

学Java有哪些就业方向?

俗话说&#xff1a;男怕入错行&#xff0c;女怕嫁错郎。众所周知&#xff0c;选工作就是选行业&#xff0c;行业和方向选对了&#xff0c;个人的发展就会随着行业风向青云直上&#xff0c;比同龄人更快的积累到财富。那究竟未来什么会是热门行业呢?这个真的很难预测&#xff0…

【1++的C++初阶】之模板(二)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C初阶】 文章目录 一&#xff0c;非类型模板参数二&#xff0c;模板特化三&#xff0c;模板分离编译 一&#xff0c;非类型模板参数 模板参数分为类类型模板参数与非类型模板参数。 类类型形…

【雕爷学编程】Arduino动手做(167)---MG996R金属齿轮舵机2

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

苹果“空间音频导航”专利曝光,提供导航指引,跟声音走就对啦?

近日&#xff0c;苹果公司成功申请一项专利&#xff0c;该专利名为“空间音频导航”&#xff0c;该专利详细说明了如何利用双耳音频设备&#xff08;AirPods或Apple Vision Pro&#xff09;为用户提供导航指引。 “空间音频导航”是一种模拟声音来源方向和距离的技术&#xff0…

STM32MP157驱动开发——按键驱动(POLL 机制)

文章目录 “POLL ”机制&#xff1a;APP执行过程驱动使用的函数应用使用的函数pollfd结构体poll函数事件类型实现原理 poll方式的按键驱动程序(stm32mp157)gpio_key_drv.cbutton_test.cMakefile修改设备树文件编译测试 “POLL ”机制&#xff1a; 使用休眠-唤醒的方式等待某个…

c# Outlook检索设定问题

基于c# 设定outlook约会予定&#xff0c;时间格式是YYYY-MM-DD HH:mm 的情报。 问题发生&#xff1a; 根据开始时间&#xff08;2023/01/01 7:00&#xff09;条件查询该时间是否存在outlook信息时&#xff0c;明明存在一条数据&#xff0c;就是查询不出来数据 c#代码 Strin…

单源最短路的扩展应用

AcWing 1137. 选择最佳线路 有一天&#xff0c;琪琪想乘坐公交车去拜访她的一位朋友。 由于琪琪非常容易晕车&#xff0c;所以她想尽快到达朋友家。 现在给定你一张城市交通路线图&#xff0c;上面包含城市的公交站台以及公交线路的具体分布。 已知城市中共包含 n 个车站…

解决 Visual Studio Code 编译器代码自动格式化

首先找到.vscode下的settings.json配置文件 将vue3snippets.enable-compile-vue-file-on-did-save-code更改为false

多个HttpSecurity配置(局部AuthenticationManager)

前言 项目用的ruoyi的扩展版本(ts版本)&#xff0c;如果有缺失类&#xff0c;可以自行下载或补充------》个人理解 实现多端token&#xff0c;多端httpSecurity&#xff0c;并且相互隔离&#xff08;局部AuthenticationManager管理认证及授权&#xff09; 在最近的项目中遇到一…

[元带你学: eMMC协议 28] eMMC 上电时序 | eMMC 上电指南

依JEDEC eMMC及经验辛苦整理,原创保护,禁止转载。 专栏 《元带你学:eMMC协议》 内容摘要 全文 1500 字, 主要内容 eMMC 上电规范 和 eMMC 上电指南, 这部分内容偏向电气特性,如果不是硬件的同学只要特别浅的了解, 一带而过。 eMMC 上电规范 eMMC 电压 VCCQ指的是接口…

min_free_kbytes

转自&#xff1a;技术分享 | MemAvailable 是怎么计算的-腾讯云开发者社区-腾讯云 背景 前两天安装 OceanBase 时遇到一个小问题&#xff1a; 很明显&#xff0c;安装OB时要求服务器可用内存至少 8G&#xff0c;不达标就无法安装。为了凑这3台10G内存的服务器我已经费了不少劲…

springMVC快速入门

springMVC快速入门 简介 MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器类划分。 M(model)&#xff1a;模型层&#xff0c;指工程中的javaBean,作用是处理数据 javaBean分为两类&#xff1a; 一类称为实体类Bean&#xff08;专门存储业务数据&#xff0c;如…