處理音訊和顯示型眼鏡的實體輸入

適用的 XR 裝置
這份指南可協助您為這類 XR 裝置打造體驗。
音訊和
螢幕眼鏡

如要擷取及處理傳送至應用程式投影活動的使用者輸入內容,或實作自訂觸控板行為,請使用間接指標輸入內容。如要處理其他類型的事件 (例如攝影機動作),請參閱本指南的下列章節。

處理攝影機動作

每當使用者按下裝置的相機按鈕,系統就會將輸入事件傳送至應用程式的投影活動,做為 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 可包含:

並非所有價值都適用於每個動作。在將原始事件視為完成的手勢之前,請檢查動作和來源。

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),以便事件繼續透過正常調度程序。

處理系統返回手勢

如果畫面需要自訂返回行為,應用程式應使用與其他活動相同的 Android API (例如 OnBackPressedDispatcherOnBackPressedCallback),處理眼鏡的返回手勢。

使用者手勢取決於眼鏡類型:

  • 在顯示型眼鏡上,向下輕觸觸控板會執行系統的返回手勢。
  • 在智慧音訊眼鏡上,在觸控板上向後滑動會執行系統的返回手勢。

當目前畫面需要攔截「返回」操作時,請註冊返回回呼,例如關閉疊加畫面或顯示退出確認畫面。

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")
    }
}

只有在有效畫面應攔截「返回」時,才應啟用回呼。如果應由預設系統或導覽行為處理「返回」操作,請停用或移除回呼。

後續步驟

為這些事件實作輸入處理作業後,您可以參閱下列主題,進一步瞭解如何處理其他類型的輸入事件: