依階段顯示修飾符細目

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。
  • Modifier.drawBehind { ... }:
    • 在可組合函式內容後方繪製畫布指令。
  • Modifier.drawWithContent { ... }:
    • 使用 drawContent() 控制繪圖順序。
  • Modifier.drawWithCache { ... }:
    • 外側區塊會在大小或版面配置變更時執行,以快取 Path、Paint 或 Brush 物件;onDrawBehind 或 onDrawWithContent 則會在每個影格繪製時執行。

重組迴圈外 - 觀察修飾符

部分修飾符會在三個影格階段以外運作,以處理無障礙功能、使用者輸入內容和生命週期觀察。

語意和無障礙功能

處理無障礙服務 (TalkBack) 和測試的語意屬性:

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

輸入、手勢和事件

在三階段影格算繪管道之外運作,接收 OS 動作事件和使用者互動:

  • 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)