Jetpack Compose 會在不同階段執行修飾符。以下細目顯示常見修飾符所屬的階段,以及評估引數或 Lambda 的時間。
第 1 階段:組合階段
這些修飾符會在 @Composable body 內同步評估引數。在此讀取的任何狀態都會向可組合項重新啟動範圍註冊依附元件,並在變更時觸發完整重組。
- 靜態維度和大小修飾符:
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 { ... }(runs the factory body during composition)
階段 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 { ... }
輸入、手勢和事件
在三階段影格算繪管道之外運作,接收 OS 動作事件和使用者互動:
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) |