Android ConstraintLayout使用攻略

原文链接 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"/><TextViewandroid: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.mzph.cn/news/6749.shtml

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

相关文章

【重点:单例模式】特殊类设计

请设计一个类&#xff0c;只能在堆上创建对象 方式如下&#xff1a; 将构造函数设置为私有&#xff0c;防止外部直接调用构造函数在栈上创建对象。向外部提供一个获取对象的static接口&#xff0c;该接口在堆上创建一个对象并返回。将拷贝构造函数设置为私有&#xff0c;并且…

webrtc QOS方法二.4(flexfec 实现可优化点)

一、冗余报文和媒体报文组织结构优化点 以单帧10个媒体报文&#xff0c;冗余度20%为例。这里webrtc输出要有10个媒体包2个冗余包。webrtc输出的报文序列如下&#xff1a; 代码实现如下&#xff1a; UlpfecGenerator::AddPacketAndGenerateFec&#xff1a;攒够足够的帧 Forwar…

【Kafka源码走读】Admin接口的客户端与服务端的连接流程

注&#xff1a;本文对应的kafka的源码的版本是trunk分支。写这篇文章的主要目的是当作自己阅读源码之后的笔记&#xff0c;写的有点凌乱&#xff0c;还望大佬们海涵&#xff0c;多谢&#xff01; 最近在写一个Web版的kafka客户端工具&#xff0c;然后查看Kafka官网&#xff0c;…

Android 屏幕适配各种宽高比的手机

由于android 手机的屏幕宽高比样式太多了&#xff0c;在设计UI时&#xff0c;很多时候&#xff0c;会因为宽高比&#xff0c;分辨率不同会有展示上的差异。 我是这样解决的 在activity的onCreate方法前&#xff0c;调用&#xff1a; fun screenFit(context: Context) {val me…

系统架构设计师-软件架构设计(2)

目录 一、基于架构的软件开发方法&#xff08;ABSD&#xff09; 1、架构需求 1.1 需求获取 1.2 标识构件 1.3 架构需求评审 2、架构设计 2.1 提出架构模型 2.2 映射构件 2.3 分析构件的相互作用 2.4 产生架构 2.5 设计评审 3、架构文档化 4、架构复审 5、架构实现 5.1 分析与…

获取大疆无人机的飞控记录数据并绘制曲线

机型M350RTK&#xff0c;其飞行记录文件为加密的&#xff0c;我的完善代码如下 gitgithub.com:huashu996/DJFlightRecordParsing2TXT.git 一、下载安装官方的DJIFlightRecord git clone gitgithub.com:dji-sdk/FlightRecordParsingLib.git飞行记录文件在打开【我的电脑】&am…

结构型设计模式之装饰器模式【设计模式系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everythi…

LiveNVR监控流媒体Onvif/RTSP功能-支持无人机、IPC等设备RTMP推流转码分发H5无插件播放也支持GB28181输出

LiveNVR支持无人机、IPC等设备RTMP推流转码分发H5无插件播放也支持GB28181输出 1、无人机推流转国标2、获取RTMP推流地址2.1、RTMP推流地址格式2.2、推流地址示例 2、设备RTMP推流3、配置拉转RTMP3.1、直播流地址格式3.2、直播流地地址示例3.3、通道配置直播流地址 4、配置级联…

深入浅出多种开发语言对接淘宝京东1688阿里巴巴等电商平台,获取实时商品详情数据API接口介绍

api接口详解大全?优秀的设计是产品变得卓越的原因设计API意味着提供有效的接口&#xff0c;可以帮助API使用者更好地了解、使用和集成&#xff0c;同时帮助人们有效地维护它每个产品都需要使用手册&#xff0c;API也不例外在API领域&#xff0c;可以将设计视为服务器和客户端之…

IDE /完整分析C4819编译错误的本质原因

文章目录 概述基本概念代码页标识符字符集和字符编码方案源字符集和执行字符集 编译器使用的字符集VS字符集配置 有何作用编译器 - 源字符集编译器 -执行字符集 Qt Creator下配置MSVC编译器参数动态库DLL字符集配置不同于可执行程序EXE总结 概述 本文将从根本原因上来分析和解…

属猴人性格及一生运势怎么样?

生肖属猴的人聪明&#xff0c;才华出众&#xff0c;是个非常会处理人际关系的生肖&#xff0c; 开朗&#xff0c;大方&#xff0c;人缘好&#xff0c;而且能说会道&#xff0c;嘴巴甜&#xff0c;也特别擅长社交&#xff0c;喜欢热闹&#xff0c; 所以属猴人不管在哪都容易受到…

数仓学习---13、报表数据导出

星光下的赶路人star的个人主页 莫见长安行乐处&#xff0c;空令岁月易蹉跎 文章目录 一、报表数据导出1.1 MySQL建库建表1.1.1 创建数据库1.1.2 创建表 1.2 数据导出1.2.1 DataX配置文件生成脚本1.2.2 编写每日导出脚本 一、报表数据导出 为方便报表应用使用数据&#xff0c;需…

Java诊断利器 Arthas-- 一款释放潜力的神器

嘿&#xff0c;你是不是对Java开发中的调试和诊断问题感到头疼&#xff1f; 别担心&#xff0c;我要告诉你一个秘密武器&#xff01;它就像是一位超级英雄&#xff0c;能够释放你的潜力&#xff0c;解决你的烦恼&#xff01;它的名字叫做Arthas&#xff0c;是一款Java诊断利器…

手写Nacos基本原理——服务注册 配置管理

手写Nacos基本原理 一、背景介绍二、 思路方案三、过程nacosService代码pom文件配置文件具体类 nacosSDK代码pom文件配置类具体类 serviceA代码pom文件配置文件具体类 serviceB代码pom文件配置文件具体类 实现效果四、总结五、升华 一、背景介绍 之前在项目开发的过程中&#…

C# List 详解五

目录 26.GetType() 27.IndexOf(T) 28.IndexOf(T, Int32) 29.IndexOf(T, Int32, Int32) 30.Insert(Int32, T) 31.InsertRange(Int32, IEnumerable) 32.LastIndexOf(T) 33.LastIndexOf(T, Int32) 34.LastIndexOf(T, Int32, Int32) …

【CAS6.6源码解析】调试Rest API接口

CAS的web层默认是基于webflow实现的&#xff0c;ui和后端是耦合在一起的&#xff0c;做前后端分离调用和调试的时候不太方便。但是好在CAS已经添加了支持Rest API的support模块&#xff0c;添加相应模块即可。 文章目录 添加依赖并重新build效果 添加依赖并重新build 具体添加…

32位Cortex-M4 MCU:LPC54607J256ET180E、LPC54605J512BD100K 180MHz嵌入式微控制器

LPC546xx 32 位微控制器(MCU) 具有丰富的外设集、极低的功耗和增强的调试功能。 LPC546xx MCU系列采用ARM Cortex-M4内核&#xff0c;可提供以太网支持&#xff0c;并设有一个TFT LCD控制器和两个CAN FD模块。LPC546xx MCU旨在提高灵活性和性能可扩展性&#xff0c;可提供高达1…

Vue3 Vite electron 开发桌面程序

Electron是一个跨平台的桌面应用程序开发框架&#xff0c;它允许开发人员使用Web技术&#xff08;如HTML、CSS和JavaScript&#xff09;构建桌面应用程序&#xff0c;这些应用程序可以在Windows、macOS和Linux等操作系统上运行。 Electron的核心是Chromium浏览器内核和Node.js…

ABAP 为N的一个数,在原来基础上浮动在-30~30

需求&#xff1a;为N的一个数&#xff0c;在原来基础上浮动在-30~30 *&---------------------------------------------------------------------* *& Report ZZZZ111 *&---------------------------------------------------------------------* *& 需求&…

【算法基础:搜索与图论】3.4 求最短路算法(Dijkstrabellman-fordspfaFloyd)

文章目录 求最短路算法总览Dijkstra朴素 Dijkstra 算法&#xff08;⭐原理讲解&#xff01;⭐重要&#xff01;&#xff09;&#xff08;用于稠密图&#xff09;例题&#xff1a;849. Dijkstra求最短路 I代码1——使用邻接表代码2——使用邻接矩阵 补充&#xff1a;稠密图和稀疏…