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/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 バリエーション(遅延フェーズ) | 状態が変化したとき |
|---|---|---|---|
| オフセット | 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) |