Compose ConstraintLayout 详讲
作者:新小梦
博客:https://juejin.cn/post/6934203680786743304
简介与依赖
Compose ConstraintLayout约束布局主要应用在构建复杂布局,避免使用Column、Row、Box多层嵌套,同时也能提高开发效率。
开始使用之前需要添加对ConstraintLayout的依赖:
implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha03'
需要注意的:截止本文发稿,Compose和Constraintlayout都还没有到稳定版本,所以对相关库的依赖一定都要更新到最新版本(或者相适配版本),不然可能存在不兼容问题。
入门与深入
1、引用创建
在View系统的ConstraintLayout在xml布局中,需要通过id进行相关引用,在Compose也是类似的。通过createRefs函数或createRef函数为不同的View预定一个引用。
@Composable
fun learnConstraintLayout(){ConstraintLayout() {//通过createRefs创建三个引用val (image,name,desc)=createRefs()}
}
2、绑定引用
将通过constrainAs函数将引用与View绑定,相当于给View赋值了一个id。另外,constarinAs有时在编写代码并不能自动提示,需要自己手刃代码哦。
@Composable
fun learnConstraintLayout(){ConstraintLayout() {//通过createRefs创建三个引用val (image,name,desc)=createRefs()Image(painter = painterResource(id = puppy.avatar),contentDescription = "dog avatar",modifier = Modifier.constrainAs(avatar) {}//通过constrainAs将Image与imageRef绑定.size(100.dp).clip(shape = RoundedCornerShape(5)),contentScale = ContentScale.Crop)}
}
通过linkTo函数将view与其他view或者parent约束。这里的parent指的就是ConstraintLayout本身。
@Composable
fun learnConstraintLayout(){ConstraintLayout() {//通过createRefs创建三个引用val (image,name,desc)=createRefs()Image(painter = painterResource(id = puppy.avatar),contentDescription = "dog avatar",modifier = Modifier.constrainAs(avatar) {top.linkTo(parent.top)start.linkTo(parent.start)end.linkTo(parent.end)bottom.linkTo(parent.bottom)}//通过constrainAs将Image与imageRef绑定,并增加约束.size(100.dp).clip(shape = RoundedCornerShape(5)),contentScale = ContentScale.Crop)}
}
constrainAs函数中的start、top、end、bottom分别代表view的左、上、右、下四条边,linkTo表示相互作用。例如代码中的top.linkTo(parent.top)表示Image的顶边和ConstraintLayout的顶边对齐,和view系统中的
layout_constraintTop_toTopOf="parent"是一致。接下来再增加两个Text。
@Composable
fun learnConstraintLayout() {ConstraintLayout() {//通过createRefs创建三个引用val (imageRef, nameRef, descRef) = createRefs()Image(painter = painterResource(id = R.mipmap.dog_avatar),contentDescription = "dog avatar",modifier = Modifier.constrainAs(imageRef) {//通过constrainAs将Image与imageRef绑定,并增加约束top.linkTo(parent.top)start.linkTo(parent.start)bottom.linkTo(parent.bottom)}.size(100.dp).clip(shape = RoundedCornerShape(5)),contentScale = ContentScale.Crop)Text(text = "名称",modifier = Modifier.constrainAs(nameRef) {top.linkTo(imageRef.top, 2.dp)start.linkTo(imageRef.end, 12.dp)end.linkTo(parent.end)width = Dimension.fillToConstraints}.fillMaxWidth(),fontSize = 18.sp,maxLines = 1,textAlign = TextAlign.Left,overflow = TextOverflow.Ellipsis,)Text(text = "描述", modifier = Modifier.constrainAs(descRef) {top.linkTo(nameRef.bottom, 5.dp)start.linkTo(nameRef.start)end.linkTo(parent.end)width = Dimension.fillToConstraints}.fillMaxWidth(),maxLines = 1,overflow = TextOverflow.Ellipsis,style = TextStyle(color = color999999, fontSize = 13.sp))}
}
在上面代码中,在ConstrantLayout中创建了Image和两个Text组件。在Text的约束,通过start.linkTo(imageRef.end, 12.dp)约束条件,将nameRef Text位与Image的右边,并增加了12dp的margin。
3、约束尺寸
注意到,给Text的宽度增加了width = Dimension.fillToConstraints约束,让Text文本过长时,不超出约束条件。
例如,默认情况下:
//将nameRef Text的约束改成下面代码
Text(text = "名称是否是否所发生的方法是否是否",modifier = Modifier.constrainAs(nameRef) {top.linkTo(imageRef.top, 2.dp)start.linkTo(imageRef.end, 12.dp)},fontSize = 18.sp,maxLines = 1,textAlign = TextAlign.Left,overflow = TextOverflow.Ellipsis,
)
通过效果图看到,Text文本过长时不仅超过了ConstraintLayout,还超出了屏幕。
将代码改成如下:
Text(text = "名称是否是否所发生的方法是否是否",modifier = Modifier.constrainAs(nameRef) {top.linkTo(imageRef.top, 2.dp)start.linkTo(imageRef.end, 12.dp)end.linkTo(parent.end,12.dp)width=Dimension.fillToConstraints},fontSize = 18.sp,maxLines = 1,textAlign = TextAlign.Left,overflow = TextOverflow.Ellipsis,
)
效果图:
Dimension取值如下:
fillToConstraints 填充约束条件下所剩的可用空间,如上面例子。
preferredWrapContent 内容自适应,但受约束条件影响,也就是说,当宽小于约束条件下可用的宽时,则view的宽就是自身的宽,但大于的时候,则受约束条件影响。高也是如此。例如:小于约束所剩宽时:
Text(text = "名称负少测试赛",modifier = Modifier.constrainAs(nameRef) {top.linkTo(imageRef.top, 2.dp)start.linkTo(imageRef.end, 12.dp)width=Dimension.preferredWrapContent},fontSize = 18.sp,textAlign = TextAlign.Left,overflow = TextOverflow.Ellipsis, )
效果图:
增加文本内容,增加右边与parent对齐。通过效果图,可见文本换行处理。
Text(text = "名称负少发发发发发发付付付付付付测试赛",modifier = Modifier.constrainAs(nameRef) {top.linkTo(imageRef.top, 2.dp)start.linkTo(imageRef.end, 12.dp)end.linkTo(parent.end)width=Dimension.preferredWrapContent},fontSize = 18.sp,textAlign = TextAlign.Left,overflow = TextOverflow.Ellipsis,
)
效果图:
wrapContent内容自适应,不受约束条件影响。
preferredValue指定固定值大小,受约束条件影响。
value指定固定值大小,不受约束条件影响。
4、居中对齐
当然,Compose ConstraintLayout也提供居中对齐,centerTo、centerHorizontallyTo、centerVerticallyTo。
例如:再增加两个Text,使其水平居中对齐。
Text(text = "年龄", modifier = Modifier.constrainAs(ageRef) {top.linkTo(descRef.bottom, 5.dp)start.linkTo(nameRef.start)},maxLines = 1,overflow = TextOverflow.Ellipsis,style = TextStyle(color = color999999, fontSize = 13.sp)
)Text(text = "颜色", modifier = Modifier.constrainAs(colorRef) {start.linkTo(ageRef.end,10.dp)centerVerticallyTo(ageRef)width = Dimension.fillToConstraints},maxLines = 1,overflow = TextOverflow.Ellipsis,style = TextStyle(color = color999999, fontSize = 13.sp)
)
效果图:
5、引导、栅栏与链
由于年龄和颜色有时为了突出显示,设置不同的大小和颜色,而时间Text想根据两者的底部处于最下的来对齐。此时就需要栅栏。
val bottomBarrier=createBottomBarrier(ageRef,colorRef,margin = 5.dp)
Text(text = "2021-02-28", modifier = Modifier.constrainAs(timeRef) {start.linkTo(nameRef.start)top.linkTo(bottomBarrier)},maxLines = 1,overflow = TextOverflow.Ellipsis,style = TextStyle(color = color999999, fontSize = 13.sp)
)
当然,可以通过createStartBarrier()、createTopBarrier()、createEndBarrier()创建不同方向的栅栏。
随着右侧文本的增加,可恶的项目经理有时要求垂直方向中间压缩,有时要求平均整个Constraintlayout的高度。这时候就需要链出场了。通过createVerticalChain和createHorizontalChain创建垂直和水平方向的链。
createVerticalChain(nameRef,descRef,ageRef,timeRef,chainStyle = ChainStyle.Spread)
6、ChainStyle的取值:
Packed:压缩
Spread:平分
SpreadInside 上下两边留View,中间View平分
从效果图SpreadInside可以看到并不是很理想,这是因为一些上下相互约束条件没有设置好。例如调整后:
也可以通过createGuidelineFromBottom,一起相关类似的api来创建引导线。引导线是不可见,起到View的对齐参考作用。
总结
其实,整体使用下来的感受,Compose ConstraintLayout约束条件的使用和View系统的ConStraintLayout是一致,简单熟悉一下API基本可以上手。如果不熟悉View系统的ConStraintLayout,建议先阅读Constraintlayout 2.0:你们要的更新来了。如果对一些API不存在或报错,建议查找官方文档,查看版本是否更新或者API更换或废弃。
另外:由于Compose已经优化深层布局嵌套,所以也就不存在使用Compose ConstraintLayout比多层嵌套使用Column和Row等等布局存在性能优势问题。只是更方便我们开发复杂布局,对齐边缘等。
ConstraintSet
ConstraintSet主要说来做动画处理,一个ConstraintSet保存一个布局的约束状态,通过约束状态的切换,来实现同个布局状态切换效果。
代码实现:
@Composable
fun learnConstraintSet() {val orientation = remember { mutableStateOf(1)}ConstraintLayout(getConstraintLayout(orientation),Modifier.padding(16.dp, 0.dp, 16.dp, 0.dp).background(color = colorEFEFEF, shape = RoundedCornerShape(5.dp)).fillMaxWidth().padding(12.dp, 12.dp, 12.dp, 12.dp)) {Image(painter = painterResource(id = R.mipmap.dog_avatar),contentDescription = "效果图片",modifier = Modifier.layoutId("imageRef").fillMaxWidth().clickable {if (orientation.value==0){orientation.value=1}else{orientation.value=0}}.clip(shape = RoundedCornerShape(5)),contentScale = ContentScale.FillWidth)Text(text = "泰迪犬其实是贵宾犬的一种。根据体型大小被分为四类,最受欢迎的是体型较小的品种:迷你贵宾犬和玩具贵宾犬。其中玩具贵宾犬是体型最小的一种,个性好动、欢快、非常机警、聪明、喜欢外出、性格脾气好、适应力强。贵宾犬不脱毛,是极好的宠物犬。如果红色玩具贵宾犬不剃胡须和嘴边的毛可以长成动漫画里面泰迪熊的模样,所以红色(褐色)玩具贵宾犬又叫“泰迪",modifier = Modifier.layoutId("titleRef"),fontSize = 18.sp,textAlign = TextAlign.Left,overflow = TextOverflow.Ellipsis,maxLines =if (orientation.value==0) Int.MAX_VALUE else 4,)}
}private fun getConstraintLayout(orientation:MutableState<Int>):ConstraintSet{return ConstraintSet {val imageRef= createRefFor("imageRef")val titleRef= createRefFor("titleRef")if (orientation.value==0){constrain(imageRef){start.linkTo(parent.start)end.linkTo(parent.end)top.linkTo(parent.top)}constrain(titleRef){start.linkTo(imageRef.start)end.linkTo(imageRef.end)top.linkTo(imageRef.bottom,16.dp)width= Dimension.fillToConstraints}}else{constrain(imageRef){start.linkTo(parent.start)top.linkTo(parent.top)width=Dimension.value(100.dp)height=Dimension.value(100.dp)}constrain(titleRef){start.linkTo(imageRef.end,8.dp)top.linkTo(imageRef.top,2.dp)end.linkTo(parent.end)bottom.linkTo(imageRef.bottom,8.dp)width= Dimension.fillToConstraintsheight= Dimension.fillToConstraints}}}
}
Compose ConstraintLayout 详讲相关推荐
- Jetpack Compose入门详解(实时更新)
Jetpack Compose入门详解 前排提醒 前言(Compose是什么) 1.实战准备 一.优势与缺点 二.前四课 三.标准布局组件 1.Column 2.Row 3.Box 四.xml和com ...
- 网络流题目详讲+题单(提高版)(持续更新中......)
网络流题目详讲+题单(提高版)(持续更新中......) 标签:图论--网络流 PS:如果你觉得自己还不够强(和我一样弱),可以去入门版看看 阅读体验:https://zybuluo.com/Junl ...
- 附005.Docker Compose文件详解
一 Docker Compose文件简介 compose文件使用yml格式,主要分为了四个区域: version:用于指定当前docker-compose.yml语法遵循哪个版本 services:服 ...
- 黑猫带你学UFS协议第1篇:全网最全UFS协议中文详讲,这份学习框架图,你值得拥有!!!(持续更新中...)
文/黑猫学长 1 作者想说 笔者本人从事于存储芯片行业多年,对eMMC/UFS/SD等芯片有深入研究,协议尤甚.而今看来,UFS协议在整个存储产品中(包括U盘.SPI.SD卡,NM卡.emmc.SSD ...
- linux软raid mdadm命令详讲
软 RAID mdadm 详讲 一.RAID 介绍 RAID 0 RAID 0(在某些 LaCie 设备中也称为 FAST 模式)是速度最快的一种 RAID 模式.它 需要至少两个驱动器,并且会将数据 ...
- Hive学习之路(二):Hive表操作详讲
操作内容简介 一.操作前的准备 二.Hive表操作详讲 1. 创建数据库 2. 查看所有数据库/表 3. 在Hive上直接操作HDFS 4. 在Hive上直接执行终端命令 5. 创建数据表/查看表的信 ...
- Java中的反射机制详讲
Java中的反射机制详讲 1.反射机制_介绍_Class对象获取 2.反射机制_动态操作_构造器_方法_属性 3.动态编译_DanamicCompile_反射调用main方法问题 好文推荐:排序.查找 ...
- 【STM32】STM32标准库与HAL库对照学习教程特别篇--系统时钟RCC详讲
[STM32]STM32标准库与HAL库对照学习教程特别篇--系统时钟RCC详讲 一.前言 二.时钟是什么 三.时钟树 1.时钟树图 2.时钟树讲解 左边部分 中间部分 右边部分 特殊部分 四.初始化 ...
- mysql mof提权原理_(新安全原创精华)Mysql扩展文件MOF提权详讲
本帖最后由 阿甫哥哥 于 2016-8-8 17:24 编辑 哈喽,大家好,我是0x_ALis,我代表新安全网络攻防研究室又来咱们的I春秋发精华帖子了. 希望大家可以支持我们,我们也会做得更好.无论是 ...
最新文章
- unity 骨骼击碎_保证击碎$ 100挑战的创新策略
- 解决外部符号错误:_main,_WinMain@16,__beginthreadex
- 【jQuery 区别】attr()和prop()的区别
- perf stat 输出解读
- python声音信号调制_用python产生正弦波和PWM信号产生脉冲幅度调制
- rpc之使用httpserver实现tpc
- 条款6:明确拒绝编译器自动生成的函数
- asp程序ajax怎么写,ASP+AJAX+ACCESS数据库实例讲解三个步骤分享
- 计算机三级 信息安全技术 题纲
- artDialog--经典的网页对话框组件
- 实现winfrom进度条及进度信息提示,winfrom程序假死处理
- 卸载抖音和微博的一天……
- 华为防火墙笔记-报文处理流程
- R语言作业一:矩估计、极大似然估计、拟合、对数正态分布、泊松分布、负二项分布
- Java入门之7:Java中的float和double类型的浮点数是怎么按照IEEE 754标准存储的?
- 服务器2016自动备份怎么取消,wps中ppt的制作怎样取消掉定时自动备份
- PHP实现阿拉伯数字转中文大写
- Unexpected state导致HMaster abort
- 金蝶K3采购暂估案例4商业模式单到冲回
- 我做了一个Python Bot,可以解决任何给定图像中的多项选择问题。 码]