アプリの投影されたアクティビティに配信されるユーザー入力をキャプチャして処理する場合や、カスタムのタッチパッド動作を実装する場合は、間接ポインタ入力を使用します。他のタイプのイベント(カメラ アクションなど)を処理するには、このガイドの以下のセクションをご覧ください。
カメラのアクションを処理する
ユーザーがデバイスのカメラボタンを押すたびに、システムは入力イベントをアプリのプロジェクション アクティビティに ProjectedInputEvent.ProjectedInputAction.TOGGLE_APP_CAMERA アクションとして配信します。アプリは、専用のディスパッチャを使用してこのアクションをモニタリングできます。
@OptIn(ExperimentalProjectedApi::class) class CameraActionInputSnippetActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Observe hardware camera action events when RESUMED lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.RESUMED) { withContext(Dispatchers.Default) { try { val projectedActivity = ProjectedActivityCompat.create(this@CameraActionInputSnippetActivity) try { projectedActivity.projectedInputEvents.collect { inputEvent -> if (inputEvent.inputAction == TOGGLE_APP_CAMERA) { withContext(Dispatchers.Main) { onCameraActionTriggered() } } } } finally { projectedActivity.close() } } catch (e: CancellationException) { throw e } catch (e: Exception) { Log.w("CameraActionSnippet", "ProjectedActivityCompat unavailable: ${e.message}") } } } } setContent { GlimmerTheme { TouchpadInputSnippet( onTap = { Log.i("CameraActionSnippet", "Touchpad tapped") } ) } } } private fun onCameraActionTriggered() { Log.i("CameraActionSnippet", "Camera action button double-pressed!") } }
一般的なモーション イベントを検査する
dispatchGenericMotionEvent を使用して、アプリのプロジェクション アクティビティに配信された汎用モーション イベントを検査します。汎用モーション イベントはアクティビティ境界で配信され、フォーカスされた Jetpack Compose Glimmer コンポーネントを必要としません。
MotionEvent には次のものを含めることができます。
- マスクされたアクション(
ACTION_DOWN、ACTION_MOVE、ACTION_UPなど)。 - ポインタの座標(
AXIS_X、AXIS_Y、AXIS_Zなど)。 - デバイス ID やソースなどのデバイスとソースの情報。
すべての値がすべてのアクションで意味を持つわけではありません。未加工のイベントを完了した操作として扱う前に、アクションとソースを検査します。
class MotionGestureInputSnippetActivity : ComponentActivity() { override fun dispatchGenericMotionEvent(ev: MotionEvent): Boolean { val actionName = when (ev.actionMasked) { MotionEvent.ACTION_DOWN -> "ACTION_DOWN" // First contact with the glasses touchpad MotionEvent.ACTION_MOVE -> "ACTION_MOVE" // Contact moving across the glasses touchpad MotionEvent.ACTION_UP -> "ACTION_UP" // Contact lifted from the glasses touchpad else -> "ACTION_${ev.actionMasked}" } Log.d( "MotionGestureSnippet", "MotionEvent: action=$actionName x=${ev.x} y=${ev.y}" ) // Delegate to super unless intentionally consuming the event return super.dispatchGenericMotionEvent(ev) } }
アクティビティがイベントを意図的に消費する場合にのみ true を返します。それ以外の場合は、super.dispatchGenericMotionEvent(ev) を返して、通常のディスパッチでイベントを続行できるようにします。
システムの「戻る」ジェスチャーを処理する
画面でカスタムの戻る動作が必要な場合、アプリは、OnBackPressedDispatcher や OnBackPressedCallback など、他のアクティビティで使用するのと同じ Android API を使用して、メガネの戻るジェスチャーを処理する必要があります。
ユーザー ジェスチャーはメガネの種類によって異なります。
- ディスプレイ グラスでは、タッチパッドを下にスワイプすると、システムの戻る操作が実行されます。
- オーディオ グラスでは、タッチパッドを逆方向にスワイプすると、システムの戻る操作が実行されます。
現在の画面で戻るボタンをインターセプトする必要がある場合(オーバーレイを閉じる、終了確認を表示するなど)に、戻るコールバックを登録します。
class BackGestureInputSnippetActivity : ComponentActivity() { private val backCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { onBackGestureReceived() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Register back gesture callback with Activity's onBackPressedDispatcher onBackPressedDispatcher.addCallback(this, backCallback) } private fun onBackGestureReceived() { Log.i("BackGestureSnippet", "System back gesture intercepted") } }
コールバックは、アクティブな画面が Back をインターセプトする必要がある場合にのみ有効にする必要があります。デフォルトのシステムまたはナビゲーションの動作で「戻る」を処理する必要がある場合は、コールバックを無効にするか削除します。
次のステップ
これらのイベントの入力処理を実装したら、以下のトピックで他の種類の入力イベントの処理について詳しく学ぶことができます。
- UI 入力について詳しくは、Jetpack Compose Glimmer のフォーカスと間接ポインタ入力の処理をご覧ください。
- 投影された入力イベントについては、
ProjectedActivityCompat、ProjectedInputEvent、ProjectedInputEvent.ProjectedInputActionをご覧ください。 - プラットフォームの入力とナビゲーションについては、
MotionEventと適切な「戻る」ナビゲーションを提供するをご覧ください。