Wear で手首の動きによる操作を使用する
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
タッチ スクリーンの使用が困難な場合でも、手首の動きを使用して、アプリを片手で簡単に操作できます。
たとえば、ユーザーは片手に飲み物のコップを持ったまま、もう片方の手で通知をスクロールできます。手首の動きを使用するその他のユースケースとしては、次のようなものがあります。
- ジョギング アプリで、歩数、経過時間、現在のペースの各表示画面を移動する
- 旅行アプリで、フライトと搭乗口の情報をスクロールする
- ニュースアプリで、記事をスクロールする
スマートウォッチ デバイスで手首の動きによる操作を確認するには、[設定] > [高度な機能] > [ジェスチャー] > [手首の操作: ON] を選択し、手首の動きによる操作が有効になっていることを確認します。次に、[チュートリアルを起動] を選択して、スマートウォッチでジェスチャーのチュートリアルを完了します。
注: 手首を振る動作は、システムレベルで「戻る」または「元に戻す」を表すジェスチャーであり、アプリでカスタマイズすることはできません。
このガイドで説明しているように、手首の動きによる操作は以下の方法で使用できます。
次の表に示すように、手首の動きによる操作はそれぞれ 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;
}
}
おすすめの方法
View
と Activity
へのキーイベントの配信については、KeyEvent
と
KeyEvent.Callback
のページをご確認ください。
- 方向アフォーダンスの一貫性を保ちます。次に進むには「手首を外側にすばやく振る」を使用し、前に戻るには「手首を内側にすばやく振る」を使用します。
- 手首の動きによる操作に対応するタップ操作を使用できるようにします。
- 視覚的なフィードバックを提供します。
- 直感に反する機能をシステムの残りの部分に実装するためにキーコードを使用しないでください。たとえば、アクションをキャンセルするか、手首をすばやく振る動作で左右の軸を移動するために、
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 UTC。
[[["わかりやすい","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 UTC。"],[],[],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."]]