2.1 Modifier 的本质
Modifier 是一个有序的装饰器链表,每个元素都是一个 Modifier.Element,它们依次对 Composable 进行变换。
Text(text = "Hello",modifier = Modifier.fillMaxWidth() // 1. 宽度撑满父布局.padding(16.dp) // 2. 四周添加 16dp 内边距.background(Color.Yellow) // 3. 背景色黄色.clickable { } // 4. 可点击
)
执行顺序:从外到内(从左到右)依次应用。上面例子中,先 fillMaxWidth,然后在撑满的基础上加 padding,再在 padding 后的区域涂背景,最后让这个区域可点击。
2.2 高频 Modifier 分类速查
尺寸与布局
| Modifier | 说明 | 示例 |
|---|---|---|
.size(width, height) |
固定宽高 | Modifier.size(48.dp) |
.width(w) / .height(h) |
单独设置宽或高 | Modifier.width(100.dp) |
.fillMaxWidth(fraction) |
撑满父宽度(可指定比例) | Modifier.fillMaxWidth(0.5f) 占一半 |
.fillMaxHeight() |
撑满父高度 | |
.fillMaxSize() |
撑满父宽高 | |
.requiredSize(...) |
强制尺寸(忽略父约束) | 慎用 |
.defaultMinSize(minW, minH) |
设置最小尺寸 |
外边距与内边距
| Modifier | 说明 |
|---|---|
.padding(all) |
四个方向统一内边距 |
.padding(start, top, end, bottom) |
分别设置 |
.padding(horizontal, vertical) |
水平/垂直 |
.offset(x, y) |
偏移(不影响布局占位) |
.wrapContentSize(align) |
让子元素按自身大小放置,可指定对齐 |
背景与边框
| Modifier | 说明 |
|---|---|
.background(color, shape) |
背景色 + 形状 |
.border(width, color, shape) |
边框 |
.clip(shape) |
裁切(不会自动添加背景) |
.shadow(elevation, shape) |
阴影(Material 组件自带) |
交互与手势
| Modifier | 说明 |
|---|---|
.clickable(enabled, onClickLabel, onClick) |
点击事件 |
.combinedClickable(onClick, onDoubleClick, onLongClick) |
组合点击 |
.selectable(selected, onClick) |
单选/多选 |
.toggleable(value, onValueChange) |
开关状态 |
.draggable(...) / .swipeable(...) |
拖拽/滑动 |
.pointerInput(block) |
自定义手势 |
滚动与嵌套
| Modifier | 说明 |
|---|---|
.verticalScroll(state) |
垂直滚动 |
.horizontalScroll(state) |
水平滚动 |
.nestedScroll(connection) |
嵌套滚动连接 |
其他
| Modifier | 说明 |
|---|---|
.alpha(float) |
透明度 |
.rotate(degrees) |
旋转 |
.scale(scaleX, scaleY) |
缩放 |
.zIndex(z) |
Z 轴顺序 |
.testTag(tag) |
测试标签 |
.graphicsLayer { } |
高效视觉变换(不触发重测) |
2.3 Modifier 顺序的经典陷阱
// 错误顺序:先 background 再 padding
Modifier.background(Color.Red) // 红色背景铺满整个可用区域.padding(16.dp) // 然后把内容往里挤 16dp,留下红色边框?// 实际上背景已经画完了,padding 只是移动内容,背景不变
// 正确顺序:先 padding 再 background
Modifier.padding(16.dp) // 预留 16dp 空白.background(Color.Red) // 红色背景只画在 padding 后的区域内
经验法则:按照"从外到内"的顺序思考。
- 尺寸约束(
fillMaxWidth,size) - 外边距/内边距(
padding,offset) - 装饰(
background,border,clip,shadow) - 交互(
clickable,pointerInput) - 滚动/手势(
scrollable,draggable)
2.4 三大布局:Column、Row、Box
Column —— 垂直线性布局
Column(modifier = Modifier.fillMaxSize().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally, // 子项水平对齐verticalArrangement = Arrangement.spacedBy(8.dp) // 子项垂直间距
) {Text("Item 1")Text("Item 2")Text("Item 3")
}
verticalArrangement 选项:
| 值 | 效果 |
|---|---|
Arrangement.Top |
顶部对齐(默认) |
Arrangement.Center |
垂直居中 |
Arrangement.Bottom |
底部对齐 |
Arrangement.SpaceEvenly |
均匀分布,两端也有间距 |
Arrangement.SpaceBetween |
两端贴边,中间均匀分布 |
Arrangement.SpaceAround |
两端半间距,中间均匀 |
Arrangement.spacedBy(dp) |
最常用:固定间距 |
horizontalAlignment 选项:Start、CenterHorizontally、End。
Row —— 水平线性布局
参数与 Column 对称:
horizontalArrangement:控制水平方向排列(对应 Column 的 verticalArrangement)verticalAlignment:控制垂直方向对齐(对应 Column 的 horizontalAlignment)
Row(modifier = Modifier.fillMaxWidth(),verticalAlignment = Alignment.CenterVertically,horizontalArrangement = Arrangement.SpaceBetween
) {Text("Left")Text("Right")
}
Box —— 层叠布局(类似 FrameLayout)
子项默认从左上角开始堆叠,可以通过 contentAlignment 设置默认对齐,或通过 Modifier.align() 单独控制每个子项的对齐。
Box(modifier = Modifier.size(200.dp).background(Color.LightGray),contentAlignment = Alignment.Center // 所有子项默认居中
) {// 底层Box(Modifier.size(150.dp).background(Color.Red))// 上层文字Text("Hello", color = Color.White)// 右上角的关闭按钮Icon(Icons.Default.Close,contentDescription = "Close",modifier = Modifier.align(Alignment.TopEnd).padding(8.dp))
}
常用对齐值:TopStart、TopCenter、TopEnd、CenterStart、Center、CenterEnd、BottomStart、BottomCenter、BottomEnd。
2.5 weight 权重 —— 在 Row/Column 中按比例分配空间
Row(Modifier.fillMaxWidth()) {Text("A", Modifier.weight(1f).background(Color.Red))Text("B", Modifier.weight(2f).background(Color.Green))Text("C", Modifier.weight(1f).background(Color.Blue))
}
// A 占 1/4,B 占 2/4,C 占 1/4
weight只能用在 Row/Column 的直接子项上。- 如果某子项没有 weight,它会先根据自身内容大小占据空间,剩下的空间才由带 weight 的子项按比例分配。
2.6 布局修饰符总结
| 场景 | 使用 |
|---|---|
| 垂直排列多个组件 | Column |
| 水平排列多个组件 | Row |
| 组件重叠(如徽标、遮罩) | Box |
| 按比例分配空间 | Modifier.weight() |
| 让组件在父布局中单独对齐 | Modifier.align() |
| 让整个布局居中 | Box(contentAlignment = Alignment.Center) |