Jetpack Compose Glimmer で間接ポインタ入力を処理する

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

onIndirectPointerGesture 修飾子を使用すると、コンポーネントは、デバイスのタッチパッドから発生するイベントなど、高レベルの間接ポインタ イベントを受信して応答できます。この修飾子を使用すると、タッチパッドなどのソースから送信されるジェスチャーをキャプチャして処理できます。

API サーフェス

アプリで処理を制御するために使用できるコールバックは 4 つあります。

  • onClick: 水平方向の大きな動きを伴わないタップまたはクリックが成功したときにトリガーされます。
  • onSwipeForward: 水平方向のスワイプが、前方方向の距離としきい値を超えたときにトリガーされます。
  • onSwipeBackward: 水平方向のスワイプが、逆方向の距離としきい値を超えたときにトリガーされます。
  • Enabled: false に設定すると、修飾子は無視され、コールバックは呼び出されません。

スワイプとスクロールのシステム動作

システムは、タッチスロップしきい値を使用して、クリックとスワイプを区別します。

  • ダウン状態中にポインタが大きく移動すると、onClick はキャンセルされます。
  • 移動中にポインタが大幅に逆戻りすると、スワイプ操作は無効になります。

例: コンポーネントのスワイプとクリックの処理を設定する

次のコードは、フォーカス可能な Box でのスワイプとクリックの処理を設定します。

@Composable
fun OnIndirectPointerGestureSample() {
    var lastGesture by remember { mutableStateOf("None") }

    Box(
        modifier =
            Modifier.fillMaxSize()
                .onIndirectPointerGesture(
                    enabled = true,
                    onSwipeForward = { lastGesture = "Forward" },
                    onSwipeBackward = { lastGesture = "Backward" },
                    onClick = { lastGesture = "Click" },
                )
                .focusTarget(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Last Gesture: $lastGesture")
    }
}

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

  • onIndirectPointerGesture にはフォーカスが必要なため、focusTarget も適用して Box をフォーカス可能にします。focusTarget または別のフォーカスを有効にする修飾子(surface など)を使用できます。フォーカスがないと、修飾子は間接ポインタイベントを処理できません。
  • この例では、onSwipeForward コールバックと onClick コールバックの両方を実装しているため、検出されたスワイプ ジェスチャーとクリック ジェスチャーはインターセプトされて消費され、親コンテナに到達しません。ただし、特定のコールバックを null のままにして、親コンテナの onIndirectPointerGesture 修飾子にジェスチャーを渡すこともできます。