各阶段的修饰符细分

Jetpack Compose 会在不同的阶段执行修饰符。以下细分显示了常见修饰符所属的阶段以及何时评估其实参或 lambda。

第 1 阶段:组合阶段

这些修饰符会在 @Composable 正文中同步评估实参。此处读取的任何状态都会向可组合函数重启范围注册依赖项,并在发生更改时触发完全重组。

  • 静态维度和尺寸调整修饰符
    • Modifier.size(dp)Modifier.width(dp)Modifier.height(dp)
    • Modifier.fillMaxSize()Modifier.fillMaxWidth()Modifier.fillMaxHeight()
    • Modifier.wrapContentSize()Modifier.wrapContentWidth()Modifier.wrapContentHeight()
    • Modifier.requiredSize()Modifier.defaultMinSize()
    • Modifier.aspectRatio(ratio)
    • Modifier.weight(weight) (在 RowScope ColumnScope 中)
    • Modifier.width(IntrinsicSize.Min / Max)
    • Modifier.height(IntrinsicSize.Min / Max)
  • 静态间距和边衬区
    • Modifier.padding(all = dp)Modifier.padding(start, top, end, bottom)
    • Modifier.windowInsetsPadding(insets)Modifier.statusBarsPadding()
  • 直接价值视觉修饰符
    • Modifier.alpha(float) (在组合期间读取状态)
    • Modifier.rotate(degrees) (在组合期间读取状态)
    • Modifier.scale(scaleX, scaleY) (在组合期间读取状态)
    • Modifier.background(color = Color, shape = Shape)
    • Modifier.border(width, color, shape)
    • Modifier.shadow(elevation, shape)
    • Modifier.clip(shape)
    • Modifier.blur(radius)
  • 静态位置修饰符
    • Modifier.offset(x = dp, y = dp) (直接值过载)
    • Modifier.absoluteOffset(x = dp, y = dp)
  • 动态可组合修饰符
    • Modifier.composed { ... } (在组合期间运行工厂主体)

第 2 阶段:布局阶段

布局阶段分为两个不同的子步骤,具有单独的失效范围:

第 2A 步:衡量

确定大小(widthheight)和限制。此处的读取状态会触发重新测量和重新放置:

  • Modifier.layout { measurable, constraints -> ... }layout(w, h) 之前的代码在衡量期间执行。

第 2B 步:放置和布局回调

确定 (x, y) 坐标位置。此处读取的状态仅触发重新放置(跳过测量和组合):

  • Modifier.offset { IntOffset(x, y) } (lambda 重载)
  • Modifier.absoluteOffset { IntOffset(x, y) } (lambda 重载)
  • Modifier.layout { ... layout(w, h) { placeable.place(x, y) } }layout(w, h) { ... } 块中的代码。
  • Modifier.onPlaced { layoutCoordinates -> ... }:在放置期间确定父坐标后调用。
  • Modifier.onSizeChanged { intSize -> ... }:如果大小发生变化,则在布局测量完成后调用。
  • Modifier.onGloballyPositioned { layoutCoordinates -> ... }:在整个窗口布局传递完成后调用。

第 3 阶段:绘制阶段

这些修饰符在画布绘制期间执行。这些代码块内的状态读取会跳过组合和布局,仅运行绘制传递:

  • Modifier.graphicsLayer { ... }:
    • 在 lambda 中更新的属性:alphatranslationXtranslationYscaleXscaleYrotationXrotationYrotationZshadowElevationshapecliprenderEffecttransformOrigin
  • Modifier.drawBehind { ... }:
    • 在可组合项内容后方绘制画布命令。
  • Modifier.drawWithContent { ... }:
    • 使用 drawContent() 控制绘制顺序。
  • Modifier.drawWithCache { ... }:
    • 外部块在大小或布局发生变化时运行,以缓存 PathPaintBrush 对象;onDrawBehindonDrawWithContent 在每个帧绘制时运行。

在重组循环之外 - 观测修饰符

有些修饰符在三个帧阶段之外运行,用于处理无障碍服务、用户输入和生命周期观测。

语义和无障碍功能

处理无障碍服务 (TalkBack) 和测试的语义属性:

  • Modifier.semantics { ... }
  • Modifier.clearAndSetSemantics { ... }

输入、手势和事件

在三阶段帧渲染流水线之外运行,接收操作系统运动事件和用户互动:

  • Modifier.pointerInput(key) { detectTapGestures { ... } } / detectDragGestures / awaitPointerEventScope
  • Modifier.clickable(enabled, onClickLabel) { ... }
  • Modifier.combinedClickable { ... }
  • Modifier.toggleable { ... }
  • Modifier.selectable { ... }
  • Modifier.draggable(...) / Modifier.scrollable(...) / Modifier.draggable2D(...)
  • Modifier.onFocusChanged { focusState -> ... }
  • Modifier.onKeyEvent { keyEvent -> ... }
  • Modifier.onVisibilityChanged { isVisible -> ... }:在协程中,当可组合项的可见性在配置的延迟时间后发生变化时,系统会调用该回调。

快速参考:价值与 Lambda 阶段

在 lambda 中读取状态值会将读取操作延迟到后续阶段,当该状态发生变化时,系统会跳过之前的阶段

修饰符 / 模式 直接价值(构成) Lambda 变体(延迟阶段) 状态发生变化时
偏移值 Modifier.offset(x, y) Modifier.offset { IntOffset(x, y) } 布局(放置)(跳过合成)
Alpha / 不透明度 Modifier.alpha(alpha) Modifier.graphicsLayer { this.alpha = alpha } 绘制(跳过构图和布局)
旋转 Modifier.rotate(degrees) Modifier.graphicsLayer { rotationZ = degrees } 绘制(跳过构图和布局)
发展壮大 Modifier.scale(scale) Modifier.graphicsLayer { scaleX = s; scaleY = s } 绘制(跳过构图和布局)
翻译 Modifier.padding(...) Modifier.graphicsLayer { translationX = ... } 绘制(跳过构图和布局)
背景色 Modifier.background(color) Modifier.drawBehind { drawRect(color) } 绘制(跳过构图和布局)
滚动 / 视差 Modifier.offset(scroll.dp) Modifier.offset { IntOffset(0, scroll) } 布局(放置)(跳过合成)

Modifier.Node 接口映射

对于使用高性能 Modifier.Node API 的自定义修饰符,阶段直接映射到节点功能接口:

阶段 Modifier.Node 接口 核心方法
布局(测量和放置) LayoutModifierNode measure(measurable, constraints)
布局(全局坐标) GlobalPositionAwareModifierNode onGloballyPositioned(coordinates)
布局(展示位置) LayoutAwareModifierNode onRemeasured(size)onPlaced(coordinates)
绘图 DrawModifierNode draw(ContentDrawScope)
输入 / 指针 PointerInputModifierNode onPointerEvent(...)onCancelPointerInput()
语义 SemanticsModifierNode applySemantics(SemanticsPropertyReceiver)
焦点 FocusEventModifierNode onFocusEvent(focusState)