Modifier 修饰符
问题
Compose 中的 Modifier 是什么?它的链式调用顺序有什么影响?
答案
1. Modifier 概述
Modifier 是 Composable 的装饰器,用于设置大小、填充、背景、点击事件等。通过链式调用组合多个修饰符。
Text(
text = "Hello",
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.background(Color.LightGray, RoundedCornerShape(8.dp))
.clickable { onClick() }
.padding(12.dp) // 内部额外填充
)
2. 顺序很重要
Modifier 的应用顺序是从外到内(从左到右),顺序不同效果不同:
// 先 padding 再 background → 背景在 padding 内部
Modifier.padding(16.dp).background(Color.Red)
// 先 background 再 padding → 背景填满,padding 在背景上
Modifier.background(Color.Red).padding(16.dp)
记忆方式
把 Modifier 想象成一层一层包裹的盒子。先写的在外层,后写的在内层。padding 先写等于外边距,后写等于内边距。
3. 常用 Modifier
| Modifier | 说明 |
|---|---|
size() / fillMaxWidth() | 设置尺寸 |
padding() | 设置内/外边距(取决于顺序) |
background() | 设置背景色/形状 |
border() | 设置边框 |
clip() | 裁剪形状 |
clickable() | 添加点击事件 |
scrollable() / verticalScroll() | 滚动 |
offset() | 偏移位置 |
alpha() | 透明度 |
shadow() / elevation | 阴影 |
weight() | Row/Column 中的权重 |
align() | Box 中的对齐 |
// 实战示例:卡片 Item
@Composable
fun ProductItem(product: Product, onClick: () -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.background(MaterialTheme.colorScheme.surface)
.clickable(onClick = onClick)
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
model = product.imageUrl,
contentDescription = null,
modifier = Modifier
.size(60.dp)
.clip(RoundedCornerShape(8.dp))
)
Spacer(modifier = Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) {
Text(product.name, maxLines = 1, overflow = TextOverflow.Ellipsis)
Text("¥${product.price}", color = MaterialTheme.colorScheme.primary)
}
}
}
4. 自定义 Modifier
// 扩展函数方式
fun Modifier.conditional(
condition: Boolean,
modifier: Modifier.() -> Modifier
): Modifier = if (condition) then(modifier(Modifier)) else this
// 使用
Modifier.conditional(isSelected) {
background(Color.Blue.copy(alpha = 0.1f))
}
常见面试问题
Q1: 为什么 Modifier 的顺序会影响结果?
答案:
Modifier 链表示一系列嵌套的包装。每个 Modifier 是一个节点,按顺序从外到内应用。比如 padding(16).background(red) 等价于:外层 16dp 空白 padding → 内层红色背景。而 background(red).padding(16) 等价于:外层红色背景 → 内层 16dp 空白 padding(视觉上 padding 在红色区域内)。
Q2: Modifier.clickable 和 Modifier.pointerInput 有什么区别?
答案:
clickable:高级 API,支持无障碍、涟漪效果、语义信息。用于简单的点击和长按pointerInput:低级 API,可以处理任意手势(拖拽、缩放、旋转)。需要手动实现手势检测
Modifier.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
// 处理拖拽
}
}
Q3: Compose 中如何实现涟漪效果?
答案:
clickable 和 combinedClickable 默认自带 Material 涟漪(ripple)效果。可以通过 indication 参数自定义:
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(bounded = true, color = Color.Blue),
onClick = { }
)
设置 indication = null 可以禁用涟漪。