Jetpack Compose - Modifier入门篇
Jetpack Compose - Modifier入门篇
- 0、介绍
- 1、属性一览
- 1.1、androidx.compose.foundation.layout包
- 1.2、androidx.compose.ui.draw包
- 1.3、androidx.compose.foundation包
- 2、使用示例
- 2.1、paddingFromBaseline
- 2.2、background
- 3、版本更新
- 4、未解决问题
Compose系列文章,请点原文阅读。原文,是时候学习Compose了!
0、介绍
一个 有序的、不可变的修饰元素集合,用于添加装饰或者行为到Compose UI元素。例如background、padding 、点击事件等。或者给Text设置单行、给Button设置各种点击状态等行为。
我们先拿XML中的FrameLayout做下对比,如下,我们在xml文件中定义了一个 宽度填充满父容器,高度200dp,背景为黑色,内容边距为16dp的 FrameLayout:
<FrameLayoutandroid:layout_width="match_parent"android:layout_height="200dp"android:background="#000000"android:padding="16dp" ><-- 可配置子级元素 --></FrameLayout>
那么在Compose中如何实现这样的UI呢?直接来看结果,了解下Modifier是如何配合Composable函数实现的:
@Composable
fun BoxDemo() {Box(modifier = Modifier.fillMaxWidth().height(200.dp).background(Color.Black).padding(16.dp),) {//可配置子级元素}
}
首先我们需要定义一个使用@Composable
注解的函数BoxDemo(),在该函数中使用Compose提供的Box()函数,来实现类似XML中的FrameLayout效果。Box()函数有一个Modifier参数,我们设置下Modifier的各种属性,例如宽度填充满父容器,可以使用.fillMaxWidth()
;高度200dp,可以使用.height(200.dp)
;背景为黑色,可以使用.background(Color.Black)
;边距16dp,可以使用.padding(16.dp)
;这样通过给Box()设置相关的修饰符,我们就可以实现所需的显示效果;
Modifier基本的使用就类似上文一样,设置或者组合不同的属性给UI函数即可。注意官方的描述中有序的一词,在使用的过程中属性定义的顺序确实会影响到UI的显示效果。我们在下文示例中再详细描述,接下来一起看下Modifier可配置的属性吧。
1、属性一览
【目前基于alpha 11版本】Modifier可配置的属性太多了,而且分布在好几个包中,如有遗漏请自行查看Compose Modifier相关文档:
1.1、androidx.compose.foundation.layout包
Modifier.width(width: Dp)
设置自身的宽度,单位dp;Modifier.widthIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)
设置自身的最小和最大宽度(当子级元素超过自身时,子级元素超出部分依旧可见);Modifier.fillMaxWidth(fraction: Float = 1f)
默认横向填充满父容器的宽度,参数可以控制宽度的比例。例如0.5就是当前元素占父元素宽度的一半;Modifier.wrapContentWidth(align: Alignment.Horizontal = Alignment.CenterHorizontally, unbounded: Boolean = false)
根据子级元素的宽度来确定自身的宽度,如果自身设置了最小宽度的话则会被忽略。当unbounded参数为true的时候,自身设置了最大宽度的话也会被忽略;Modifier.preferredWidth(width: Dp)
设置自身的首选宽度,单位dp;Modifier.preferredWidth(intrinsicSize: IntrinsicSize)
设置自身的首选宽度为与子级元素的最小或最大宽度相同(还在实验阶段);Modifier.preferredWidthIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)
设置自身的首选最小和最大宽度;
以上就是宽度的相关属性,那么类似的,高度属性如下所示(就不再具体说明啦):
Modifier.height(height: Dp)
Modifier.heightIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)
Modifier.fillMaxHeight(fraction: Float = 1f)
Modifier.wrapContentHeight(align: Alignment.Vertical = Alignment.CenterVertically, unbounded: Boolean = false)
Modifier.preferredHeight(intrinsicSize: IntrinsicSize)
Modifier.preferredHeight(height: Dp)
Modifier.preferredHeightIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)
OK,宽高分别的属性定义都有了,假如我想同时控制宽高的属性呢?有!请看size相关函数:
Modifier.size(size: Dp)
Modifier.size(width: Dp, height: Dp)
Modifier.sizeIn(minWidth: Dp = Dp.Unspecified, minHeight: Dp = Dp.Unspecified, maxWidth: Dp = Dp.Unspecified, maxHeight: Dp = Dp.Unspecified)
Modifier.fillMaxSize(fraction: Float = 1f)
Modifier.wrapContentSize(align: Alignment = Alignment.Center, unbounded: Boolean = false)
Modifier.preferredSize(size: Dp)
Modifier.preferredSize(width: Dp, height: Dp)
Modifier.preferredSizeIn(minWidth: Dp = Dp.Unspecified, minHeight: Dp = Dp.Unspecified, maxWidth: Dp = Dp.Unspecified, maxHeight: Dp = Dp.Unspecified)
接下来到了设置填充(padding)的时间了:
Modifier.padding(start: Dp = 0.dp, top: Dp = 0.dp, end: Dp = 0.dp, bottom: Dp = 0.dp)
分别在四个方向上设置填充;Modifier.padding(horizontal: Dp = 0.dp, vertical: Dp = 0.dp)
分别在横向和纵向上设置填充;Modifier.padding(all: Dp)
统一设置所有方向上的填充;Modifier.padding(padding: PaddingValues)
根据参数PaddingValues来设置填充,PaddingValues参数可以理解为以上三种方式的封装;Modifier.absolutePadding(left: Dp = 0.dp, top: Dp = 0.dp, right: Dp = 0.dp, bottom: Dp = 0.dp)
不处理国际化问题,按照绝对的上下左右方向设置填充;
以下两个是针对有Text情况下的填充,因为有BaseLine等相关属性(不了解Baseline的可以先百度搜索下:TextView Baseline先进行阅读),阅读类App对该属性要求可能比较严格,平常开发中貌似几乎没有使用过类似属性。下面简单说下这几个函数(以博主本人的语言功底应该是描述不清楚的,所以后文我们会根据示例实际演示下):
Modifier.paddingFromBaseline(top: Dp = Dp.Unspecified, bottom: Dp = Dp.Unspecified)
Modifier.paddingFromBaseline(top: TextUnit = TextUnit.Unspecified, bottom: TextUnit = TextUnit.Unspecified)
当子级元素有Baseline属性时,例如子级元素有Text,那么 .paddingFromBaseline(top = 50.dp) 表示文本 第一行 Baseline的位置距离父级 顶部 为50dp, .paddingFromBaseline(bottom= 50.dp) 表示文本 最后一行 Baseline的位置距离父级 底部 为50dp。请看下文示例2.1 。 (在API28,XML中TextView提供了 android:firstBaselineToTopHeight="" 属性,对应这个就可以很好理解了)
上文面只是讲解了单位为dp情况下的内容,当单位为TextUnit的时候道理类似,只是Text可以设置为16.sp或者16.em。
Modifier.paddingFrom(alignmentLine: AlignmentLine, before: Dp = Dp.Unspecified, after: Dp = Dp.Unspecified)
Modifier.paddingFrom(alignmentLine: AlignmentLine, before: TextUnit = TextUnit.Unspecified, after: TextUnit = TextUnit.Unspecified)
Modifier.relativePaddingFrom(alignmentLine: AlignmentLine, before: Dp = Dp.Unspecified, after: Dp = Dp.Unspecified)
以上几个函数暂时还未研究,待续。
接下来是margin的时间,啊?翻遍了文档,没有margin属性,是不是官方不建议我们使用margin这种方式了呢?可能是建议我们使用padding或者Spacer()函数来实现?那我们来看下offset,乍一看好像能实现类似的margin属性,但是实际情况不是这么用的,应该是让我们在做动画的时候使用该函数:
Modifier.offset(x: Dp = 0.dp, y: Dp = 0.dp)
水平和竖直方向上的偏移,单位dp,值可以为正也可以为负,无需考虑国际化的问题。Modifier.offset(offset: Density.() -> IntOffset)
偏移,单位px,可以结合动画进行元素的偏移处理;Modifier.offsetPx(x: State<Float> = mutableStateOf(0f), y: State<Float> = mutableStateOf(0f))
带有状态的偏移量【已废弃】,请使用上一个函数;Modifier.absoluteOffset(x: Dp = 0.dp, y: Dp = 0.dp)
Modifier.absoluteOffset(offset: Density.() -> IntOffset)
Modifier.absoluteOffsetPx(x: State<Float> = mutableStateOf(0f), y: State<Float> = mutableStateOf(0f))
不考虑国际化情况下的偏移,使用绝对方向
Modifier.aspectRatio(ratio: Float, matchHeightConstraintsFirst: Boolean = false)
按照宽高比例进行设置,例如以下代码可以绘制出宽度为80dp,高度为40dp的一个Box(该函数还有待研究,绝不会这么简单):Box(modifier = Modifier.width(80.dp).aspectRatio(ratio = 2f, matchHeightConstraintsFirst = false),)
androidx.compose.foundation.layout包中的修饰符属性我们先研究这么多,下一个包!
1.2、androidx.compose.ui.draw包
Modifier.alpha(alpha: Float)
不透明度,范围从0-1;Modifier.clip(shape: Shape)
裁剪为相应的形状,例如shape = RoundedCornerShape(20) 表示裁剪为20%圆角的矩形。这个时候需要注意了,如果你结合background()函数,那么有必要注意下顺序,必须clip()在前,background()在后。否则的话背景色不会被裁切。Modifier.clipToBounds()
暂时还不清楚作用;Modifier.drawOpacity(opacity: Float)
不透明度,已废弃,请使用alpha函数Modifier.drawShadow(elevation: Dp, shape: Shape = RectangleShape, clip: Boolean = elevation > 0.dp)
绘制阴影效果,已废弃,请使用shadow函数Modifier.shadow(elevation: Dp, shape: Shape = RectangleShape, clip: Boolean = elevation > 0.dp)
绘制阴影效果Modifier.rotate(degrees: Float)
设置视图围绕其中心旋转的角度;Modifier.scale(scaleX: Float, scaleY: Float)
Modifier.scale(scale: Float)
设置视图的缩放比例;
1.3、androidx.compose.foundation包
背景边框相关
Modifier.background(color: Color, shape: Shape = RectangleShape)
设置背景色;Modifier.background(brush: Brush, shape: Shape = RectangleShape, alpha: Float = 1.0f)
使用Brush来设置背景色,例如常见的渐变色效果,见下文2.2示例;Modifier.border(border: BorderStroke, shape: Shape = RectangleShape)
绘制指定形状的边框,渐变色效果使用该函数可以实现;Modifier.border(width: Dp, color: Color, shape: Shape = RectangleShape)
绘制指定宽度、颜色、形状的边框;Modifier.border(width: Dp, brush: Brush, shape: Shape)
绘制指定宽度、brush、形状的边框,渐变色效果可以使用该函数实现;
点击事件相关
Modifier.clickable(enabled: Boolean = true, onClickLabel: String? = null, role: Role? = null, onLongClickLabel: String? = null, onLongClick: () -> Unit = null, onDoubleClick: () -> Unit = null, onClick: () -> Unit)
Modifier.clickable(enabled: Boolean = true, interactionState: InteractionState, indication: Indication?, onClickLabel: String? = null, role: Role? = null, onLongClickLabel: String? = null, onLongClick: () -> Unit = null, onDoubleClick: () -> Unit = null, onClick: () -> Unit)
可以看到,启用状态enabled、响应状态interactionState、单击、双击、长按事件都可以在此处处理。具体使用请查看系列文章的Button相关。
滚动相关
在alpha11版本之前,滚动视图是ScrollableRow、ScrollableColumn实现的。在alpha 11版本,Modifier中添加了如下两个函数,在Row或者Column中,我们使用这两个函数就可以在子级元素过宽、过长情况下开启滚动模式了。
Modifier.horizontalScroll(state: ScrollState, enabled: Boolean = true, reverseScrolling: Boolean = false)
Modifier.verticalScroll(state: ScrollState, enabled: Boolean = true, reverseScrolling: Boolean = false)
具体使用示例请查看系列文章之【Jetpack Compose - Row、Column】;
2、使用示例
2.1、paddingFromBaseline
首先我们实现如下布局,蓝色Box中所有子级元素居中处理,所以红色分割线是居中线,我们下文需要参考该线进行理解。绿色Box中按照默认布局方式分别添加了黄色Box和白色Text两个元素。
全部代码如下所示:
@Composable
fun BoxDemo() {Box(modifier = Modifier.width(400.dp).height(120.dp).background(myBlue),contentAlignment = Alignment.Center) {Box(modifier = Modifier.width(100.dp).height(100.dp).background(color = myGreen)) {Box(modifier = Modifier.fillMaxWidth().height(40.dp).background(color = myYellow),)Text(modifier = Modifier.wrapContentSize(),text = "Compose",color = Color.White)}//水平分割线Divider(modifier = Modifier.fillMaxWidth().height(2.dp).background(color = myRed))}
}
当我们给绿色Box添加.paddingFromBaseline(top = 50.dp)
属性后,可以看到UI显示效果为:
文本:绿色Box的宽高为100dp,设置该属性后,表示Text的Baseline位置需要位于高度为50dp处,也就是在红线标志的位置,所以文本整体的摆放如上所示。
黄色Box:可以看到黄色Box并不是从绿色Box的50dp处开始摆放的,而是从Text顶部开始摆放。怎么理解?假如Text的Baseline到Text顶部的距离是10dp,那么目前博主也就是理解为.paddingFromBaseline(top = 50.dp)
等于 .padding(top = (50-10).dp)
(如果此处有疑问请一定及时告知博主,唯恐误导各位同学)。
当我们保留上述属性,但是去掉Text元素的时候,显示效果又如下所示,此时我们不妨理解为,没有Baseline属性的元素时,.paddingFromBaseline(top = 50.dp)
等于 .padding(top = 50.dp)
:
2.2、background
如何实现渐变色的效果呢,使用Brush,直接看代码:
@Composable
fun GradientBox() {val colorList = arrayListOf(Color(0xFF25BC6B), Color(0xFFFFCA1C))Box(modifier = Modifier.width(200.dp).height(50.dp).background(brush = Brush.horizontalGradient(colorList),shape = RoundedCornerShape(50)))
}
如下所示,还有shape指定的圆角效果哦:
3、版本更新
- 暂无
4、未解决问题
关于Modifier其实还有很多特殊情况我们可能都没有遇到,本文只是重点列出了博主在实际开发中遇到的一些基础问题,后续遇到其他情况欢迎各位一起探讨。
到进阶篇的话我们会涉及到动画、自定义视图、手势等相关内容,一起努力吧!!!
Jetpack Compose - Modifier入门篇相关推荐
- 《Jetpack Compose 从入门到实战》带你踏上 Compose 开发之旅~
写书的契机 Jetpack Compose 首次亮相于 2019 年的 Google I/O 大会,彼时的我正在为抖音客户端研发一款基于原生视图渲染的声明式 UI 框架,由于声明式开发理念在当时还过于 ...
- Jetpack Compose 从入门到入门(六)
本篇说说Compose中的Canvas. 1. Canvas @Composable fun Canvas(modifier: Modifier,onDraw: DrawScope.() -> ...
- Jetpack Compose 从入门到入门(三)
本篇开始介绍Jetpack Compose 中的修饰符Modifier.修饰符可以用来执行以下操作: 更改可组合项的大小.布局.行为和外观. 添加信息,如无障碍标签. 处理用户输入. 添加高级互动,如 ...
- Jetpack Compose 从入门到入门(四)
本篇开始介绍Jetpack Compose 中常用的组件.有一部分之前的文章中也出现过,今天详细说明一下. 1. Text 日常最常用的应该就是显示文字,所以有必要说一下Text控件.首先源码如下: ...
- Jetpack Compose中的Modifier
Modifier的基本使用 Modifier修饰符是Jetpack Compose中用来修饰组件的,提供常用的属性,写布局时几乎所有Composable组件的大部分属性都可以用Modifier 来修饰 ...
- Android原生UI开发框架 《Jetpack Compose入门到精通》最全上手指南
前言 在去年的Google/IO大会上,亮相了一个全新的 Android 原生 UI 开发框架-Jetpack Compose, 与苹果的SwiftIUI一样,Jetpack Compose是一个声明 ...
- 重磅首发!Jetpack Compose 完全开发手册,从入门到精通!
前 言 Jetpack 架构组件 及 标准化开发模式 的确立,意味着 Android 开发已步入成熟阶段.现在的Android岗招人的时候也非常看重应试者对 Jetpack 架构组件的理解程度. 今天 ...
- Jetpack Compose中的手势操作
点击事件 监听点击事件非常简单,使用 clickable 和 combinedClickable 修饰符即可满足需求: @OptIn(ExperimentalFoundationApi::class) ...
- Android 我的第一个Jetpack Compose应用
目录 1. 背景 2. Jetpack Compose 是什么? 3. 开始前的准备 4. 创建DEMO 4.1 New Project 4.2 项目配置 5. 项目整体变化 5.1 布局部分 5.2 ...
- Android 开发新技术:Jetpack Compose当仁不让
前言 Jetpack Compose是用于构建原生Android 界面的新款工具包. 平时我们开发Android界面都是靠XML画出来,但是Compose 则是用代码来写界面,和Flutter写法有点 ...
最新文章
- 字节跳动一面:i++ 是线程安全的吗?
- java query接口_「软帝学院」Java零基础学习详解
- Calibre 3.38.1 下载 Runoob 网站中的《Python 2 教程》的 Recipe
- 多部门数据分析需求,如何满足?
- node.js express 启用 https
- 睡眠多少分钟一个循环_睡眠分为几个阶段每个阶段大概多少时间?
- netty的使用部署
- 扫描控件Web在线Applet
- Angualr 加载速度慢,为页面初始化完成前添加loading
- 三维实景建模技术在智慧交通领域的新发展与深入应用
- 自旋锁学习系列(2):TAS锁
- 信息安全-保研面试经历总结
- 上海牌照(沪牌)拍牌,软件,手动
- PFC161台湾应广单片机PFC161S08A/PFC161S08B带硬件触摸功能单片机
- zabbix配置拓扑图标签及链路流量
- 下载阿里云免费ssl证书
- 多个wordpress共享用户信息、共享Cookie
- html5页面拨打电话,5.添加页面/设置点击拨打电话
- 一招解决matplot绘图中文无法显示的问题
- word中设置奇偶页页眉页脚
热门文章
- APARNET阿帕网
- HTML系列之水平线标签hr
- 内网liunx环境升级nginx版本(因为nginx 0.6.x < 1.20.1 1-Byte Memory Overwrite RCE 系统漏洞而升级)
- 2022年第十二届APMCM亚太地区数学建模竞赛1月加赛E题翻译以及思路
- VB.NET模拟掷骰子
- 吴恩达深度学习系列笔记
- METS(护理类)一级考试的信效度分析及其对教学的作用
- Sutton reinforcement learning _ Chapter 2 Multi-armed Bandits
- 自下而上合并排序算法
- 在“动物杂交:新视野”中快速赚钱的9种方法