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 步:衡量
确定大小(width、height)和限制。此处的读取状态会触发重新测量和重新放置:
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 中更新的属性:
alpha、translationX、translationY、scaleX、scaleY、rotationX、rotationY、rotationZ、shadowElevation、shape、clip、renderEffect、transformOrigin。
- 在 lambda 中更新的属性:
Modifier.drawBehind { ... }:- 在可组合项内容后方绘制画布命令。
Modifier.drawWithContent { ... }:- 使用
drawContent()控制绘制顺序。
- 使用
Modifier.drawWithCache { ... }:- 外部块在大小或布局发生变化时运行,以缓存
Path、Paint或Brush对象;onDrawBehind或onDrawWithContent在每个帧绘制时运行。
- 外部块在大小或布局发生变化时运行,以缓存
在重组循环之外 - 观测修饰符
有些修饰符在三个帧阶段之外运行,用于处理无障碍服务、用户输入和生命周期观测。
语义和无障碍功能
处理无障碍服务 (TalkBack) 和测试的语义属性:
Modifier.semantics { ... }Modifier.clearAndSetSemantics { ... }
输入、手势和事件
在三阶段帧渲染流水线之外运行,接收操作系统运动事件和用户互动:
Modifier.pointerInput(key) { detectTapGestures { ... } }/detectDragGestures/awaitPointerEventScopeModifier.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) |