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入门篇相关推荐

  1. 《Jetpack Compose 从入门到实战》带你踏上 Compose 开发之旅~

    写书的契机 Jetpack Compose 首次亮相于 2019 年的 Google I/O 大会,彼时的我正在为抖音客户端研发一款基于原生视图渲染的声明式 UI 框架,由于声明式开发理念在当时还过于 ...

  2. Jetpack Compose 从入门到入门(六)

    本篇说说Compose中的Canvas. 1. Canvas @Composable fun Canvas(modifier: Modifier,onDraw: DrawScope.() -> ...

  3. Jetpack Compose 从入门到入门(三)

    本篇开始介绍Jetpack Compose 中的修饰符Modifier.修饰符可以用来执行以下操作: 更改可组合项的大小.布局.行为和外观. 添加信息,如无障碍标签. 处理用户输入. 添加高级互动,如 ...

  4. Jetpack Compose 从入门到入门(四)

    本篇开始介绍Jetpack Compose 中常用的组件.有一部分之前的文章中也出现过,今天详细说明一下. 1. Text 日常最常用的应该就是显示文字,所以有必要说一下Text控件.首先源码如下: ...

  5. Jetpack Compose中的Modifier

    Modifier的基本使用 Modifier修饰符是Jetpack Compose中用来修饰组件的,提供常用的属性,写布局时几乎所有Composable组件的大部分属性都可以用Modifier 来修饰 ...

  6. Android原生UI开发框架 《Jetpack Compose入门到精通》最全上手指南

    前言 在去年的Google/IO大会上,亮相了一个全新的 Android 原生 UI 开发框架-Jetpack Compose, 与苹果的SwiftIUI一样,Jetpack Compose是一个声明 ...

  7. 重磅首发!Jetpack Compose 完全开发手册,从入门到精通!

    前 言 Jetpack 架构组件 及 标准化开发模式 的确立,意味着 Android 开发已步入成熟阶段.现在的Android岗招人的时候也非常看重应试者对 Jetpack 架构组件的理解程度. 今天 ...

  8. Jetpack Compose中的手势操作

    点击事件 监听点击事件非常简单,使用 clickable 和 combinedClickable 修饰符即可满足需求: @OptIn(ExperimentalFoundationApi::class) ...

  9. Android 我的第一个Jetpack Compose应用

    目录 1. 背景 2. Jetpack Compose 是什么? 3. 开始前的准备 4. 创建DEMO 4.1 New Project 4.2 项目配置 5. 项目整体变化 5.1 布局部分 5.2 ...

  10. Android 开发新技术:Jetpack Compose当仁不让

    前言 Jetpack Compose是用于构建原生Android 界面的新款工具包. 平时我们开发Android界面都是靠XML画出来,但是Compose 则是用代码来写界面,和Flutter写法有点 ...

最新文章

  1. 字节跳动一面:i++ 是线程安全的吗?
  2. java query接口_「软帝学院」Java零基础学习详解
  3. Calibre 3.38.1 下载 Runoob 网站中的《Python 2 教程》的 Recipe
  4. 多部门数据分析需求,如何满足?
  5. node.js express 启用 https
  6. 睡眠多少分钟一个循环_睡眠分为几个阶段每个阶段大概多少时间?
  7. netty的使用部署
  8. 扫描控件Web在线Applet
  9. Angualr 加载速度慢,为页面初始化完成前添加loading
  10. 三维实景建模技术在智慧交通领域的新发展与深入应用
  11. 自旋锁学习系列(2):TAS锁
  12. 信息安全-保研面试经历总结
  13. 上海牌照(沪牌)拍牌,软件,手动
  14. PFC161台湾应广单片机PFC161S08A/PFC161S08B带硬件触摸功能单片机
  15. zabbix配置拓扑图标签及链路流量
  16. 下载阿里云免费ssl证书
  17. 多个wordpress共享用户信息、共享Cookie
  18. html5页面拨打电话,5.添加页面/设置点击拨打电话
  19. 一招解决matplot绘图中文无法显示的问题
  20. word中设置奇偶页页眉页脚

热门文章

  1. APARNET阿帕网
  2. HTML系列之水平线标签hr
  3. 内网liunx环境升级nginx版本(因为nginx 0.6.x < 1.20.1 1-Byte Memory Overwrite RCE 系统漏洞而升级)
  4. 2022年第十二届APMCM亚太地区数学建模竞赛1月加赛E题翻译以及思路
  5. VB.NET模拟掷骰子
  6. 吴恩达深度学习系列笔记
  7. METS(护理类)一级考试的信效度分析及其对教学的作用
  8. Sutton reinforcement learning _ Chapter 2 Multi-armed Bandits
  9. 自下而上合并排序算法
  10. 在“动物杂交:新视野”中快速赚钱的9种方法