在 Wear 上使用手腕手勢
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
手腕手勢可讓您在不方便觸控螢幕時,用單手快速使用應用程式。
舉例來說,使用者可以一手拿著水杯,一手捲動畫面來查看通知。手腕手勢的其他用途包括:
- 在慢跑應用程式中,透過垂直畫面查看跑步步數、經過時間和當前配速
- 在旅遊應用程式中,捲動畫面來查看航班和登機門資訊
- 在新聞應用程式中,捲動畫面來瀏覽文章
如要查看手錶裝置上的手腕手勢,請依序點選「設定」>「進階功能」>「手勢」>「開啟手腕手勢」,確認手勢功能已開啟。接著,選取「啟動教學課程」,在手錶上完成手勢教學課程。
注意:搖動手腕是整個系統級別的返回或復原手勢,不適用於應用程式自訂的動作。
如本指南所述,您可以透過以下方式使用手腕手勢:
每個手腕手勢都會對應到 KeyEvent
類別的 int
常數,如下表所示:
使用曲線版面配置以支援手腕手勢
WearableRecyclerView
類別會提供清單用的「曲線版面配置」,並自動支援手腕手勢。該類別已針對檢視區塊含有焦點時做出的手腕手勢,預先定義了動作。如要進一步瞭解如何使用 WearableRecyclerView
類別,請參閱「在 Wear OS 建立清單」。另請參閱本指南的「最佳做法」一節。
注意:WearableRecyclerView
類別會取代穿戴式裝置支援資料庫中類似的已淘汰類別。
即使您使用 WearableRecyclerView
,也可能需要使用 KeyEvent
類別中的常數。您可以對 WearableRecyclerView
建立子類別,並重新導入 onKeyDown()
回呼,藉此覆寫預先定義的動作。您可以使用 setEnableGestureNavigation(false)
完全停用該行為。
詳情請參閱「處理鍵盤動作」一文。
直接使用按鍵事件
您可以在
WearableRecyclerView
之外使用按鍵事件,以觸發回應手勢事件的新動作。重要的是,當裝置處於正常模式時,系統會辨識這些手勢事件,並以與所有按鍵事件相同的方式傳遞。
就像其他任何按鍵事件一樣,實作
KeyEvent.Callback
且與使用者互動相關的類別 (例如 View
或 Activity
),可以監聽與手腕手勢相關的按鍵事件。Android 架構會透過按鍵事件,呼叫含有焦點的 View
或 Activity
。如果是手勢,則系統會在做出手勢動作時呼叫 onKeyDown()
方法回呼。
舉例來說,應用程式可以覆寫實作 KeyEvent.Callback
的 View
或 Activity
中的預先定義動作,如下所示:
Kotlin
class GesturesActivity : Activity() {
/* KeyEvent.Callback */
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return when (keyCode) {
KeyEvent.KEYCODE_NAVIGATE_NEXT ->
// Do something that advances a user View to the next item in an ordered list.
moveToNextItem()
KeyEvent.KEYCODE_NAVIGATE_PREVIOUS ->
// Do something that advances a user View to the previous item in an ordered list.
moveToPreviousItem()
else -> {
// If you did not handle it, let it be handled by the next possible element as determined
// by the Activity.
super.onKeyDown(keyCode, event)
}
}
}
/** Shows the next item in the custom list. */
private fun moveToNextItem(): Boolean {
...
// Return true if handled successfully, otherwise return false.
return false
}
/** Shows the previous item in the custom list. */
private fun moveToPreviousItem(): Boolean {
...
// Return true if handled successfully, otherwise return false.
return false
}
}
Java
public final class GesturesActivity extends Activity {
@Override /* KeyEvent.Callback */
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_NAVIGATE_NEXT:
// Do something that advances a user View to the next item in an ordered list.
return moveToNextItem();
case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:
// Do something that advances a user View to the previous item in an ordered list.
return moveToPreviousItem();
}
// If you did not handle it, let it be handled by the next possible element as determined by the Activity.
return super.onKeyDown(keyCode, event);
}
/** Shows the next item in the custom list. */
private boolean moveToNextItem() {
boolean handled = false;
...
// Return true if handled successfully, otherwise return false.
return handled;
}
/** Shows the previous item in the custom list. */
private boolean moveToPreviousItem() {
boolean handled = false;
...
// Return true if handled successfully, otherwise return false.
return handled;
}
}
最佳做法
- 查看
KeyEvent
和
KeyEvent.Callback
頁面,將按鍵事件傳送至您的 View
和 Activity
。
- 使用一致的方向功能提示:使用「手腕向外轉動」手勢可前往下一項,使用「手腕向內轉動」手勢可前往上一項。
- 使用與手勢對應的觸控功能。
- 提供視覺化回饋。
- 請勿使用按鍵碼對系統其他部分實作反直覺的功能。例如,請勿使用
KEYCODE_NAVIGATE_NEXT
取消動作,或用轉動手腕手勢移動左右軸。
- 請不要攔截不屬於使用者介面的元素上的按鍵事件,例如在畫面外或部分遭遮擋的檢視區塊。這點與其他按鍵事件相同。
- 請不要將重複的轉動手腕手勢重新解讀成自己的新手勢。這可能會與系統的「搖動手腕」手勢發生衝突。
檢視區塊必須具有 ,才能接收手勢按鍵事件。請參閱
View.setFocusable()
。
系統會將手勢視為按鍵事件,因此會觸發轉換程序使系統退出「觸控模式」,這可能會發生非預期的狀況。由於使用者可能會同時使用觸控和手勢,因此或許需要使用
View::setFocusableInTouchmode()
方法。在某些情況下,可能也需要使用 setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS)
,如此一來,當「觸控模式」變更為其他模式時,或由其他模式變更為觸控模式時,目標檢視區塊就會獲得焦點。
- 請謹慎使用
requestFocus()
和 clearFocus()
:
- 呼叫
requestFocus()
時,請確保檢視區塊適合擁有焦點。如果檢視區塊位於螢幕畫面之外,或遭其他檢視區塊遮擋,當手勢觸發回呼時,就可能發生意外狀況。
clearFocus()
方法會啟動焦點搜尋,以尋找其他適合的檢視區塊。視檢視區塊階層而定,這項搜尋可能需要較複雜的計算。但最終也會將焦點指派給您不希望其接收焦點的檢視區塊。
系統會先將按鍵事件傳送至檢視區塊階層中具有焦點的檢視區塊。如果聚焦的檢視區塊無法處理該事件 (也就是回傳 false
),該事件就不會傳送至父項檢視區塊,即使該檢視區塊可以接收焦點且具有
KeyListener
也一樣。相反地,該事件會傳送至當前容納擁有焦點的檢視區塊階層的活動。
因此,您可能必須在較高層級擷取所有事件,然後再將相關程式碼向下傳送。或者,您也可以對活動建立子類別,並且視需要覆寫
dispatchKeyEvent(KeyEvent event)
方法,以便攔截相應按鍵,如果先前未在較低層級對活動進行處理,也可以進行這項作業。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-26 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-26 (世界標準時間)。"],[],[],null,["# Use wrist gestures on Wear\n\nWrist gestures can enable quick, one-handed interactions with your app\nwhen a touch screen is inconvenient.\n\n\nFor example, a user can scroll\nthrough notifications with one hand while holding a cup of water with the\nother. Other use cases for wrist gestures include the following:\n\n- In a jogging app, navigating through vertical screens that show the steps taken, time elapsed, and current pace\n- In a travel app, scrolling through flight and gate information\n- In a news app, scrolling through articles\n\n\nTo review the [wrist gestures](https://support.google.com/androidwear/answer/6312406) on a watch\ndevice, confirm that gestures are\nturned on by selecting **Settings \\\u003e Advanced features \\\u003e Gestures \\\u003e Wrist Gestures\nOn** . Then complete the\nGestures tutorial on the watch by selecting **Launch Tutorial**.\n\n\n**Note:** Shaking the wrist is the system-wide back or undo gesture\nand is not available for apps to customize.\n\n\nWrist gestures can be used in the following ways, as described in this guide:\n\n- With a [curved layout](#using_wrv), which has predefined gesture actions\n- By using [key events directly](#using_key_events) to define new user actions\n\n\nEach wrist gesture is mapped to an `int` constant from the\n[KeyEvent](/reference/android/view/KeyEvent)\nclass, as shown in the following table:\n\n| Gesture | KeyEvent | Description |\n|-----------------|-------------------------------------------------------------------------------------------|------------------------------------------|\n| Flick wrist out | [`KEYCODE_NAVIGATE_NEXT`](/reference/android/view/KeyEvent#KEYCODE_NAVIGATE_NEXT) | This key code goes to the next item. |\n| Flick wrist in | [`KEYCODE_NAVIGATE_PREVIOUS`](/reference/android/view/KeyEvent#KEYCODE_NAVIGATE_PREVIOUS) | This key code goes to the previous item. |\n\nUse a curved layout to support wrist gestures\n---------------------------------------------\n\n\nThe [WearableRecyclerView](/reference/androidx/wear/widget/WearableRecyclerView) class provides a curved\nlayout for lists and automatically supports\nwrist gestures. The class has predefined actions for occurrences of\nwrist gestures when the view has focus. For information about using\nthe `WearableRecyclerView` class, see [Create lists on Wear OS](/training/wearables/ui/lists). Also, see the\n[Best practices](#best_practices) section of this guide.\n\n\n**Note:** The `WearableRecyclerView` class replaces a similar,\n[deprecated](/training/wearables/ui/wear-ui-library#deprecations) class in the Wearable Support Library.\n\n\nEven if you use a `WearableRecyclerView`, you might want to use\nconstants from the [KeyEvent](/reference/android/view/KeyEvent)\nclass. The predefined actions can be overridden by subclassing the\n`WearableRecyclerView` and re-implementing the\n`onKeyDown()` callback. The behavior can be disabled entirely\nby using [`setEnableGestureNavigation(false)`](/reference/android/support/wearable/view/WearableListView#setEnableGestureNavigation(boolean)).\nFor more information, see\n[Handle keyboard actions](/training/keyboard-input/commands).\n\nUse key events directly\n-----------------------\n\n\nYou can use key events outside of a [WearableRecyclerView](/reference/androidx/wear/widget/WearableRecyclerView) to trigger new actions in response to gesture\nevents. Importantly, these gesture events are recognized when a device is in\nactive mode, and they are delivered in the same way as all key events.\n\n\nA class that relates to user interaction, such as a `View` or an\n`Activity`, and that implements\n[KeyEvent.Callback](/reference/android/view/KeyEvent.Callback) can listen to key events that relate to\nwrist gestures just as it can listed to any other key event. The Android framework\ncalls the `View` or `Activity` that has\nfocus with the key events. For gestures, the `onKeyDown()`\nmethod callback is called when gestures occur.\n\n\nAs an example, an app can override predefined actions in a `View`\nor `Activity` that implements `KeyEvent.Callback` as follows: \n\n### Kotlin\n\n```kotlin\nclass GesturesActivity : Activity() {\n\n /* KeyEvent.Callback */\n override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {\n return when (keyCode) {\n KeyEvent.KEYCODE_NAVIGATE_NEXT -\u003e\n // Do something that advances a user View to the next item in an ordered list.\n moveToNextItem()\n KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -\u003e\n // Do something that advances a user View to the previous item in an ordered list.\n moveToPreviousItem()\n else -\u003e {\n // If you did not handle it, let it be handled by the next possible element as determined\n // by the Activity.\n super.onKeyDown(keyCode, event)\n }\n }\n }\n\n /** Shows the next item in the custom list. */\n private fun moveToNextItem(): Boolean {\n ...\n // Return true if handled successfully, otherwise return false.\n return false\n }\n\n /** Shows the previous item in the custom list. */\n private fun moveToPreviousItem(): Boolean {\n ...\n // Return true if handled successfully, otherwise return false.\n return false\n }\n}\n```\n\n### Java\n\n```java\npublic final class GesturesActivity extends Activity {\n\n @Override /* KeyEvent.Callback */\n public boolean onKeyDown(int keyCode, KeyEvent event) {\n switch (keyCode) {\n case KeyEvent.KEYCODE_NAVIGATE_NEXT:\n // Do something that advances a user View to the next item in an ordered list.\n return moveToNextItem();\n case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:\n // Do something that advances a user View to the previous item in an ordered list.\n return moveToPreviousItem();\n }\n // If you did not handle it, let it be handled by the next possible element as determined by the Activity.\n return super.onKeyDown(keyCode, event);\n }\n\n /** Shows the next item in the custom list. */\n private boolean moveToNextItem() {\n boolean handled = false;\n ...\n // Return true if handled successfully, otherwise return false.\n return handled;\n }\n\n /** Shows the previous item in the custom list. */\n private boolean moveToPreviousItem() {\n boolean handled = false;\n ...\n // Return true if handled successfully, otherwise return false.\n return handled;\n }\n}\n```\n\nBest practices\n--------------\n\n- Review the [KeyEvent](/reference/android/view/KeyEvent) and [KeyEvent.Callback](/reference/android/view/KeyEvent.Callback) pages for the delivery of key events to your `View` and `Activity`.\n- Keep a consistent directional affordance: use \"flick wrist out\" for next and \"flick wrist in\" for previous.\n- Have a touch parallel for a gesture.\n- Provide visual feedback.\n- Don't use a keycode to implement functionality that would be counterintuitive to the rest of the system. For example, don't use `KEYCODE_NAVIGATE_NEXT` to cancel an action or to navigate the left-right axis with flicks.\n- Don't intercept the key events on elements that are not part of the user interface, such as views that are offscreen or partially covered. This is the same as for any key event.\n- Don't reinterpret repeated flick gestures into your own novel gesture. This might conflict with the system's \"shaking the wrist\" gesture.\n- For a view to receive gesture key events, it must have [focus](/reference/android/view/View#attr_android:focusable); see [`\n View.setFocusable()`](/reference/android/view/View#setFocusable(boolean)).\n\n Because gestures are treated as key events,\n they trigger a transition out of \"touch mode\" that might do unexpected\n things. Since users may alternate between using touch and\n gestures, the [`\n View::setFocusableInTouchmode()`](/reference/android/view/View#setFocusableInTouchMode(boolean)) method could be necessary. In some\n cases, it also could be necessary to use\n `setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS)` so\n that when focus changes after a change to or from touch mode, your\n intended view gets the focus.\n- Use [requestFocus()](/reference/android/view/View#requestFocus()) and [clearFocus()](/reference/android/view/View#clearFocus()) carefully:\n - When calling `requestFocus()`, make sure it's appropriate for the view to have focus. If the view is offscreen or is covered by another view, surprises can occur when gestures trigger callbacks.\n - The `clearFocus()` method initiates a focus search to find another suitable view. Depending on the view hierarchy, this search might require nontrivial computation. It can also end up assigning focus to a view you don't expect to receive focus.\n- Key events are delivered first to the view with focus in the view\n hierarchy. If the focused view does not handle the event---in other words, it returns\n `false`---the event is not delivered to the parent view, even\n if it can receive focus and has a [`\n KeyListener`](/reference/android/text/method/KeyListener). Rather, the event is delivered to the current activity\n holding the view hierarchy with focus.\n\n Therefore, it might be necessary to\n catch all events at the higher level, then pass relevant codes down.\n Alternatively, you might subclass the activity and override the\n [dispatchKeyEvent(KeyEvent event)](/reference/android/app/Activity#dispatchKeyEvent(android.view.KeyEvent)) method to intercept keys\n when necessary or handle them when they are not handled at\n lower layers."]]