Modifier:有顺序的节点链 · AndroidX 源码指南
AAndroidX 源码指南
Compose UI
Compose 底层 · androidx.compose.ui

Modifier:有顺序的节点链1.13.0-alpha01

理解 Modifier 顺序、复用和自定义 Modifier.Node 的边界。

最后更新 2026-08-01

顺序会改变结果

// padding 在 clickable 之后:padding 区域也参与点击
Modifier
    .clickable(onClick = onClick)
    .padding(16.dp)

// 交换顺序:padding 区域不在点击链内
Modifier
    .padding(16.dp)
    .clickable(onClick = onClick)

顺序影响所有阶段:

阶段受顺序影响的例子
布局weight vs padding 的先后改变尺寸计算
绘制background vs graphicsLayer 的图层关系
输入clickable vs pointerInput 的命中区域
语义testTag vs contentDescription 的暴露方式

原则:布局类(size/padding)放前面,绘制/输入类(background/clickable)放后面,可预测性最好。

Modifier 本身不可变

每次扩展返回新链,安全复用公共前缀:

val itemModifier = Modifier
    .fillMaxWidth()
    .padding(horizontal = 16.dp)

Text("A", itemModifier)
Text("B", itemModifier)   // 各自独立的链,互不影响

scope 约束:依赖特定 scope 的 modifier(weightalign)只能在对应父布局的 scope 内使用,不能抽到外部复用。

条件组合

val modifier = Modifier
    .fillMaxWidth()
    .then(if (isSelected) Modifier.background(selectedColor) else Modifier)
    .then(customModifier)

.then()if 分支条件拼接;避免用空字符串/魔数控制行为。

自定义扩展还是 Node

场景方案
只组合现有 modifierfun Modifier.myStyle() = ...(扩展函数)
需要长期状态(缓存测量结果)ModifierNodeElement + Modifier.Node
高频更新(每帧)Modifier.Node(避免每帧分配)
参与底层布局/绘制/输入Modifier.Node

业务页面优先组合现有 API;Node 是库作者和性能敏感基础设施的工具。

常见陷阱

  • 顺序错误:padding 与 clickable 顺序影响点击区域。
  • scope 泄漏weight 用在错误父布局外编译错误。
  • 每帧创建新 modifierremember 缓存稳定的 modifier 实例。
  • 不理解 then()Modifier.then 是拼接的底层实现,条件组合用 if + then

复制即用

@Composable
fun CardItem(
    text: String,
    selected: Boolean,
    onClick: () -> Unit,
) {
    val modifier = Modifier
        .fillMaxWidth()
        .padding(16.dp)
        .then(
            if (selected) {
                Modifier.background(MaterialTheme.colorScheme.primaryContainer)
            } else {
                Modifier
            }
        )
        .clickable(onClick = onClick)

    Text(text, modifier)
}

要点

  • Modifier 链顺序决定布局/绘制/输入/语义的行为。
  • 不可变、可复用;scope 相关 modifier 不能跨父布局。
  • 组合用扩展函数,需要状态/高频用 Modifier.Node。
  • 条件拼接用 if + then

相关页面