在 Wear OS 7 (API 級別 37) 以上版本中,單手手勢架構和 Compose for Wear OS 的 API,可讓使用者不必觸控就能與應用程式互動。
雖然一開始僅支援 Pixel Watch 裝置 (Pixel Watch 3 以上版本),但這個架構適用於所有原始設備製造商 (OEM)。採用這個 API 後,隨著硬體支援擴大,應用程式的手勢支援會自動在整個生態系統中擴充。
為了協助使用者探索可用的手勢,同時避免 UI 雜亂,Wear OS 架構提供動畫手勢指標。這些視覺提示會醒目顯示可執行手勢的位置,系統則會根據使用者偏好設定,自動管理顯示節奏和靜音頻率。
支援的手勢和動作
Wear OS 手勢架構支援兩種手勢類型:
- 主要動作 (雙指捏合兩下):對應至畫面上的主要動作,例如接聽來電或切換媒體播放。
- 關閉動作 (轉動手腕):對應至返回導覽、關閉對話方塊或取消提示。
在 Compose 中設定手勢
雖然單手手勢 API 可以強化 UI,但請務必注意,部分硬體和原始設備製造商 (OEM) 不支援這些手勢。如果 API 偵測到應用程式在不支援的裝置上執行,程式庫會自動不執行任何操作,且不會影響標準觸控互動。
與標準 Compose 行為一樣,您可以使用修飾符在 UI 元素上啟用單手手勢。您可以根據要執行的動作 (主要或關閉) 設定應用程式的手勢,並使用 gestureId 配合系統層級的使用者偏好設定,例如提示顯示節奏和頻率靜音。您可以建立 OneHandedGestureConfiguration 物件來表示這項設定;建議您使用 rememberOneHandedGestureConfiguration 函式建立。您也可以在 OneHandedGestureConfiguration 中提供手勢優先順序。
rememberOneHandedGestureConfiguration 函式會追蹤各次重組的使用者互動記錄,但不會公開應用程式狀態。應用程式建立設定後,應將設定傳遞至互動式可組合項上的 Modifier.oneHandedGesture。
為協助使用者探索可用的手勢,程式庫提供了 OneHandedGestureClickIndicator 方法。這個方法會做為包裝函式,取代其基礎內容,向使用者指出可執行手勢動作。
互動式元件
如要在按鈕等互動式控制項上啟用手勢,請建立指定 OneHandedGestureAction.Primary 的設定,並套用 oneHandedGesture 修飾符。將相同的 MutableInteractionSource 傳遞至控制項和修飾符,讓手勢事件在控制項上發出視覺按壓回饋。
如要啟用手勢指標,請建立並記住 OneHandedGestureClickIndicatorState 的例項。接著,如要觸發視覺回饋,請在 oneHandedGesture 修飾符提供的 onGestureAvailable 回呼中呼叫 showIndicator,向系統表示已發生指示事件。呼叫後,元件會短暫將一般內容替換為手勢動畫。
var isPlaying by remember { mutableStateOf(false) } val onClick = { isPlaying = !isPlaying } val gestureConfig = rememberOneHandedGestureConfiguration( action = OneHandedGestureAction.Primary ) val indicatorState = remember { OneHandedGestureClickIndicatorState() } val coroutineScope = rememberCoroutineScope() val interactionSource = remember { MutableInteractionSource() } Button( onClick = onClick, interactionSource = interactionSource, modifier = Modifier .fillMaxWidth() .oneHandedGesture( gestureConfiguration = gestureConfig, interactionSource = interactionSource, onGestureLabel = if (isPlaying) "pause" else "play", onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } }, onGesture = onClick ) ) { OneHandedGestureClickIndicator( gestureConfiguration = gestureConfig, state = indicatorState ) { Text(if (isPlaying) "Pause" else "Play", modifier = Modifier.fillMaxWidth()) } }
可捲動的容器
如果是可捲動的畫面或清單,請建立指定 OneHandedGestureAction.Primary 的設定,並將 oneHandedGesture 修飾符套用至容器,呼叫 scrollDown 等捲動輔助程式。
如要為捲動動作提供視覺回饋,可以使用 OneHandedGestureScrollIndicator。這個元件可做為標準捲動指標,顯示捲動位置,但也能向使用者指出可使用捲動手勢。這個指標通常會傳遞至 ScreenScaffold 的 scrollIndicator 槽,並與可捲動容器 (例如 TransformingLazyColumn) 的狀態結合。它也會觀察 OneHandedGestureScrollIndicatorState,管理視覺轉換。
如要觸發視覺回饋,請在這個狀態上呼叫 showIndicator,通常是在 oneHandedGesture 修飾符的 onGestureAvailable 回呼中。觸發後,指標會暫時將標準視覺狀態替換為手勢動畫序列,提醒使用者。
val scrollState = rememberTransformingLazyColumnState() val gestureConfig = rememberOneHandedGestureConfiguration( action = OneHandedGestureAction.Primary, priority = OneHandedGesturePriority.Scrollable ) val indicatorState = remember(gestureConfig) { OneHandedGestureScrollIndicatorState() } val coroutineScope = rememberCoroutineScope() ScreenScaffold( scrollState = scrollState, scrollIndicator = { OneHandedGestureScrollIndicator( gestureConfiguration = gestureConfig, indicatorState = indicatorState, scrollState = scrollState, modifier = Modifier.align(Alignment.CenterEnd) ) } ) { contentPadding -> TransformingLazyColumn( state = scrollState, contentPadding = contentPadding, modifier = Modifier .fillMaxSize() .oneHandedGesture( gestureConfiguration = gestureConfig, onGestureLabel = "scroll", onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } }, onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) } ) ) { items(10) { index -> Text("Item $index", modifier = Modifier.padding(8.dp)) } } }
結合多種手勢
您可以將 gesturePriority 新增至 OneHandedGestureConfiguration 物件,設定具有相同主要動作的捲動手勢和點擊手勢:
OneHandedGesturePriority.Clickable(最高):指派給互動式控制項 (例如類型為Button或Card的控制項),以便在螢幕上顯示時擷取手勢。OneHandedGesturePriority.Scrollable(中):指派給可捲動或可分頁的容器,讓容器優先處理可點擊的子項,但在沒有可點擊的控制項時捲動。OneHandedGesturePriority.Unspecified(最低):未指派優先順序。如果手勢未設定priority,則這是預設值。
只要在內部按鈕上明確設定 priority = OneHandedGesturePriority.Clickable,並在其父項清單上設定 priority = OneHandedGesturePriority.Scrollable,系統就能顯示這種手勢優先行為。使用者透過單手手勢觸發主要動作時,系統會先向下捲動清單,直到按鈕顯示,然後擷取按鈕的點擊動作。
使用 ADB 測試手勢並偵錯
您可以使用 Android Debug Bridge (adb) 和 IWearGestureService 系統服務,在實體裝置或模擬器上測試單手手勢,而不必實際移動手腕。
啟用手勢模擬
使用 ADB 模擬手勢前,請先調整裝置設定和限制覆寫設定:
確認 Wear OS 裝置搭載 Wear OS 7 (API 級別 37) 以上版本:
adb shell getprop ro.build.version.sdk如果您是在實體裝置上測試,但裝置並未戴在手腕上,或放在充電器上,請覆寫離體限制,讓手勢架構保持啟用狀態:
adb shell cmd IWearGestureService override-constraints offbody-state
使用 ADB 觸發手勢事件
如要模擬「雙指捏兩下」手勢 (Pixel Watch 上的 Primary 動作),請執行下列 ADB 殼層指令:
adb shell cmd IWearGestureService gesture DoublePinch
如要模擬「轉動手腕」手勢 (Pixel Watch 上的 Dismiss 動作),請執行下列 ADB 殼層指令:
adb shell cmd IWearGestureService gesture WristTurn
重設手勢提示追蹤
系統會追蹤使用者互動記錄,並根據全域頻率設定 (例如「Always」或「Daily」) 顯示浮動手勢提示。偵錯應用程式的手勢指標時,請重設這項追蹤記錄,讓套件再次顯示提示:
在
userdebug版本或模擬器上:adb shell cmd IWearGestureService hint clear <your_package_name>零售 (
user) 版本:在沒有 Root 權限的商用裝置上,
hint clear會遭到系統權限封鎖。清除應用程式的店面資料,重設提示探索功能:adb shell pm clear <your_package_name>
還原預設限制
測試完畢後,如要重設所有偵錯限制覆寫值,請按照下列步驟操作:
adb shell cmd IWearGestureService override-constraints reset
排解手勢插入問題
如果應用程式未收到模擬手勢:
確認手錶螢幕已喚醒並開啟。當螢幕關閉或處於微光模式時,手勢架構不會將手勢分派給應用程式。如要使用 ADB 喚醒螢幕,請執行:
adb shell input keyevent KEYCODE_WAKEUP檢查應用程式是否已註冊為有效手勢訂閱者,且目前具有視窗焦點:
adb shell cmd IWearGestureService get-active-gestures -readable當應用程式的手勢畫面位於前景,且螢幕處於喚醒狀態時,這個指令會傳回
[DoublePinch]或[DoublePinch, WristTurn]。如果傳回空白清單 ([]),請檢查視窗是否處於焦點狀態,或是否因離身限制而無法啟用。檢查內部手勢服務狀態和有效訂閱者權杖:
adb shell dumpsys IWearGestureService
其他資源
如需單手手勢的使用時機和位置設計指南,請參閱「單手手勢」。
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 單手手勢設計指南