Jetpack Compose Glimmer のサーフェス

対象の XR デバイス
このガイダンスは、次のようなタイプの XR デバイス向けのエクスペリエンスを構築する際に役立ちます。
ディスプレイ グラス

Jetpack Compose Glimmer の surface コンポーネントは、ボタンやカードなどのコンポーネントの明確な視覚領域または物理的な境界を表す基本的な構成要素です。

サーフェスは、次の視覚的および物理的プロパティを担当します。

  • クリッピング: 子を指定した形状にクリップします。
  • Border: コンポーネントの境界を強調するために内側の枠線を描画します。フォーカスされると、フォーカス ハイライト付きの太い枠線が描画されます。
  • 背景: サーフェス領域に背景色を適用します。
  • 奥行き効果: コンポーネントの状態(デフォルトとフォーカスなど)に基づいて DepthEffect シャドウをレンダリングします。
  • コンテンツの色: サーフェス内のテキストやアイコンの色を提供します。デフォルトでは背景色から計算されます。
  • インタラクションの状態: サーフェスが押されると押されたオーバーレイを描画し、フォーカスされるとハイライト付きの太い枠線を描画します。

例: サーフェスを作成する

次のコードは、クリッピング、背景、デフォルトの境界線を含むサーフェスを作成します。

@Composable
fun SurfaceSample() {
    Box(Modifier.surface().padding(horizontal = 24.dp, vertical = 20.dp)) {
        Text("This is a surface")
    }
}

Interaction and Focus

Surfaces aren't focusable by default, so users can't interact with them. In most cases, surfaces should be interactive to let users consistently move focus and navigate between components. You can use the Compose focusable modifer for surfaces that are only intended to be focusable, or the Compose clickable modifer and other modifiers for surfaces that require actions.

You can create a focusable surface by combining a surface modifier with the focusable modifier:

@Composable
fun FocusableSurfaceSample() {
    val interactionSource = remember { MutableInteractionSource() }
    Box(
        Modifier.surface(
                // Provide the same interaction source here and to focusable to make sure that
                // surface appears focused when interacted with.
                interactionSource = interactionSource
            )
            .focusable(interactionSource = interactionSource)
            .padding(horizontal = 24.dp, vertical = 20.dp)
    ) {
        Text("This is a focusable surface")
    }
}

Key points about the code

  • Shared interaction source: Both .surface() and .focusable() must share the same interactionSource. This lets the surface react to focus changes.

Similarly, you can create a clickable surface:

@Composable
fun ClickableSurfaceSample() {
    val interactionSource = remember { MutableInteractionSource() }
    Box(
        Modifier.surface(
                // Provide the same interaction source here and to clickable to make sure that
                // surface appears focused and pressed when interacted with
                interactionSource = interactionSource
            )
            .clickable(interactionSource = interactionSource, onClick = {})
            .padding(horizontal = 24.dp, vertical = 20.dp)
    ) {
        Text("This is a clickable surface")
    }
}

コードに関する主なポイント

  • 共有インタラクション ソース: 両方。surface() と 。clickable() は同じ interactionSource を共有する必要があります。これにより、視覚的な状態(押下やフォーカスなど)が同期され、ユーザー入力に対してサーフェスが視覚的に反応できるようになります。

  • 修飾子の順序: 修飾子の順序は重要です。理由 。surface() はレイアウトをクリップし、に配置します。clickable() は、タップ ターゲットがサーフェスの形状に制約されるようにします。の場合。clickable() が最初にある場合、操作エリアがコンポーネントの表示されているクリップされた境界を超えて拡張される可能性があります。

SurfaceDepthEffect

SurfaceDepthEffect クラスは、インタラクション状態間のシャドーの遷移を管理します。

  • depthEffect: サーフェスがデフォルトの状態のときに使用されるシャドウ効果。
  • focusedDepthEffect: サーフェスがフォーカスされているときに使用されるシャドウ効果。