D2Modifier
统一挂尺寸、边距、背景、点击;链式调用,顺序有意义。写界面第二高频(第一是状态)。
Modifier 是什么
概念
XML 里尺寸、padding、背景、点击散在属性、style、代码三处。Compose 收成一条链:几乎每个组件都有 modifier: Modifier = Modifier,你往上点方法即可。
和 XML 对照
| 你想做的事 | XML | Compose |
|---|---|---|
| 宽高 / 撑满 | layout_width/height | size / fillMaxWidth… |
| 内边距 | padding | padding |
| 背景 | background / drawable | background / clip |
| 点击 | setOnClickListener | clickable |
| 按比例分空间 | layout_weight | weight(Row/Column 内) |
怎么用
@Composable
fun ModifierChainDemo() {
Text(
"Hello",
modifier = Modifier
.padding(16.dp)
.background(Color.LightGray)
.clickable { /* 点击 */ }
)
}
Modifier 是空起点;每个方法返回新的 Modifier,所以可一直链式追加。不可变、纯函数式拼装。
易错点
- 把 Modifier 当成「改已经画好的 View」——它是声明链,顺序不同结果不同(见下一节案例)。
- 组件忘了暴露
modifier参数——自定义 Composable 应把 modifier 接到根节点,方便外层排版。
★ 常用属性
概念
天天写的那一批:尺寸、padding、背景/边框/裁剪、点击、以及布局作用域里的 weight / align。
和 XML 对照 + 怎么用
① 尺寸与占据 ★
// 作为某组件的 modifier 参数,例如 Text("hi", modifier = …)
Modifier.size(48.dp)
Modifier.size(width = 48.dp, height = 24.dp)
Modifier.fillMaxWidth()
Modifier.fillMaxHeight(0.5f)
Modifier.width(120.dp)
Modifier.widthIn(min = 80.dp, max = 200.dp)
fillMax* ≈ match_parent;固定 size / width ≈ 定死或 wrap 思路。Row/Column 内按比例分空间用 weight(⑤)。
② padding ★
Modifier.padding(16.dp)
Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
Modifier.padding(start = 8.dp, end = 8.dp, top = 4.dp, bottom = 4.dp)
③ 背景、边框、裁剪 ★
Modifier.background(Color.Blue)
Modifier.background(Color.Red, shape = RoundedCornerShape(8.dp))
Modifier.border(1.dp, Color.Gray, RoundedCornerShape(8.dp))
Modifier.clip(RoundedCornerShape(50))
默认直角。要圆角:background(..., shape) 或配合 clip;阴影用 shadow(○ 节)。
④ 点击 ★
Modifier.clickable { /* 单击 */ }
Modifier.clickable(enabled = false) { /* 禁用 */ }
整行可点时,把 clickable 挂在行容器上(见下方案例),别只给文字加点击。
⑤ weight ★(Row / Column 作用域)
@Composable
fun WeightDemo() {
Row(modifier = Modifier.fillMaxWidth()) {
Text("左", modifier = Modifier.weight(1f))
Text("右", modifier = Modifier.weight(2f))
}
}
≈ layout_weight。只对 Row/Column 的直接子项有效;详见布局 · Row。
⑥ align ★(Box 作用域)
@Composable
fun AlignDemo() {
Box(modifier = Modifier.size(200.dp)) {
Text("居中", modifier = Modifier.align(Alignment.Center))
Text("右上", modifier = Modifier.align(Alignment.TopEnd))
}
}
≈ FrameLayout 的 layout_gravity。详见布局 · Box。
易错点
weight/align写在错误作用域 → 编译报错或无效。- 圆角背景漏了
shape/clip→ 仍是直角色块。 - 可点区域比视觉小——把
clickable放在更大的父 Modifier 上,或保证 padding 在 clickable 内侧/外侧符合预期(顺序!)。
▶ 先 padding 再 background,和反过来差在哪
同一组修饰符,顺序一换,红块和留白关系完全不同。下面每侧:代码 + 效果示意。
@Composable
fun BgThenPadding() {
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Red)
.padding(16.dp)
)
}
@Composable
fun PaddingThenBg() {
Box(
modifier = Modifier
.padding(16.dp)
.size(100.dp)
.background(Color.Red)
)
}
要点:每个修饰符都基于「前面已经形成的盒子」再加工。调不顺时,先检查链顺序,而不是再加一层 padding 碰运气。
💡 想真机预览:把任一侧函数贴进工程,加 @Preview 即可对照。第三方网页编辑器对 Android Compose 支持不稳定,手册以示意 + Studio Preview 为准。
🔗 @Preview 官方说明
▶ 整行可点的设置项
设置列表一行:左文案、右箭头,整行都能点。XML 常给 item 根布局设 click;Compose 把 clickable + fillMaxWidth + padding 挂在 Row 上。
@Composable
fun SettingsClickRow(
title: String,
onClick: () -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onClick)
.padding(horizontal = 16.dp, vertical = 14.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
title,
modifier = Modifier.weight(1f)
)
Text("›")
}
}
要点:clickable 放在 padding 前,点击热区含边距;若先 padding 再 clickable,热区可能变小(再验证一次顺序口诀)。
💡 复制到 Studio,加 @Preview 点一下即可验证热区。@Preview
○ 偶尔属性
概念
用得到再查,不必一次背完。汇总也会进属性总表。
和 XML 对照 / 怎么用
① 变换与层级 ○
modifier.offset(x = 8.dp, y = 8.dp) // 偏移,不改布局占位
Modifier.rotate(45f)
Modifier.scale(1.2f)
Modifier.alpha(0.5f)
Modifier.zIndex(1f) // Box 内叠放顺序
offset ≈ translation,占位仍在原处;真正挤开兄弟用 padding / 布局参数。
② 滚动 / 键盘 ○
@Composable
fun ScrollDemo() {
Column(
modifier = Modifier.verticalScroll(rememberScrollState())
) {
// 内容超高时可滚
}
Column(
modifier = Modifier
.imePadding()
.verticalScroll(rememberScrollState())
) {
// 键盘弹出时顶起内容
}
}
长列表优先 Lazy,不要用可滚 Column 硬塞几千项。
③ 阴影 ○
modifier
.shadow(elevation = 4.dp, shape = RoundedCornerShape(8.dp))
.clip(RoundedCornerShape(8.dp))
.background(Color.White)
易错点
- 用
offset当「布局间距」→ 重叠/点不到,改用 padding 或 Arrangement。 verticalScroll嵌套 Lazy → 手势冲突,列表章再讲清。
抽成扩展函数
概念
同一串 Modifier 多处复制时,抽成 Modifier 扩展(≈ XML 自定义 style),全项目统一皮肤。
和 XML 对照
XML:style="@style/Card"。Compose:Modifier.cardStyle(),还能在调用处继续链式追加。
怎么用
// 顶层扩展:定义在 @Composable 之外
fun Modifier.cardStyle(): Modifier = this
.fillMaxWidth()
.padding(12.dp)
.clip(RoundedCornerShape(12.dp))
.background(Color.White)
@Composable
fun CardStyleDemo() {
Box(modifier = Modifier.cardStyle()) {
Text("卡片一")
}
Box(modifier = Modifier.cardStyle().padding(20.dp)) {
Text("卡片二") // 链式继续追加
}
}
易错点
- 扩展里写死业务点击 / 状态——样式归样式,交互参数仍由调用方传入。
- 扩展不返回
Modifier(不从this起手)→ 调用处无法继续点链。
频率速览
| 属性 | 作用 | 频率 |
|---|---|---|
padding | 内边距 | ★ 常用 |
size / fillMaxWidth | 尺寸 / 撑满 | ★ 常用 |
background / border / clip | 外观 | ★ 常用 |
clickable | 点击 | ★ 常用 |
weight | Row/Column 分空间 | ★ 常用 |
align | Box 内定位 | ★ 常用 |
offset / alpha / shadow | 变换 / 阴影 | ○ 偶尔 |
verticalScroll / imePadding | 滚动 / 键盘 | ○ 偶尔 |