フェーズ別の修飾子の内訳

Jetpack Compose は、異なるフェーズで修飾子を実行します。次の内訳は、一般的な修飾子がどのフェーズに属し、引数またはラムダがいつ評価されるかを示しています。

フェーズ 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: レイアウト フェーズ

レイアウト フェーズは、無効化スコープが異なる 2 つのサブステップに分かれています。

ステップ 2A: 測定

サイズ(width、height)と制約を決定します。ここで状態を読み取ると、再測定と再配置がトリガーされます。

  • Modifier.layout { measurable, constraints -> ... }: 測定中に layout(w, h) の前のコードが実行されます。

ステップ 2B: プレースメントとレイアウトのコールバック

(x, y) 座標の位置を決定します。ここで読み取られた状態は、再配置のみをトリガーします(測定とコンポジションはスキップされます)。

  • Modifier.offset { IntOffset(x, y) } (ラムダのオーバーロード)
  • Modifier.absoluteOffset { IntOffset(x, y) } (ラムダのオーバーロード)
  • Modifier.layout { ... layout(w, h) { placeable.place(x, y) } }: layout(w, h) { ... } ブロック内のコード。
  • Modifier.onPlaced { layoutCoordinates -> ... }: 配置中に親座標が決定された後に呼び出されます。
  • Modifier.onSizeChanged { intSize -> ... }: サイズが変更された場合、レイアウトの測定が完了した後に呼び出されます。
  • Modifier.onGloballyPositioned { layoutCoordinates -> ... }: ウィンドウ レイアウトのパス全体が終了した後に呼び出されます。

フェーズ 3: 描画フェーズ

これらの修飾子は、キャンバスの描画中に実行されます。これらのブロック内の状態の読み取りは、コンポジションとレイアウトの両方をスキップし、描画パスのみを実行します。

  • Modifier.graphicsLayer { ... }:
    • ラムダで更新されるプロパティ: 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 は、各フレームの描画時に実行されます。

再コンポーズ ループの外側 - 観察修飾子

一部の修飾子は、3 つのフレーム フェーズの外で動作し、ユーザー補助、ユーザー入力、ライフサイクル オブザーバを処理します。

セマンティクスとアクセシビリティ

ユーザー補助機能サービス(TalkBack)とテストのセマンティクス プロパティを処理します。

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

入力、ジェスチャー、イベント

3 フェーズのフレーム レンダリング パイプラインの外部で動作し、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 バリエーション(遅延フェーズ) 状態が変化したとき
オフセット Modifier.offset(x, y) Modifier.offset { IntOffset(x, y) } レイアウト(配置)(コンポジションをスキップ)
アルファ / 不透明度 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)