一部の Wear OS デバイスには、物理的な回転サイドボタンが配置されています。ユーザーがボタンを回すと、アプリの現在のビューが上または下にスクロールします。このタイプの入力はロータリー入力と呼ばれます。
注: このガイドでは、主にビューベースの UI を使用してロータリー入力を処理する方法について説明します。Wear OS 向け Compose を使用したロータリー入力の処理について詳しくは、Compose のロータリー入力をご覧ください。
ScrollView
、ListView
、HorizontalScrollView
、WearableRecyclerView
など、スクロール可能なコンテナの多くは、フォーカスされている場合に Wear OS 固有のコードを必要とすることなくロータリー入力をサポートします。Android 9(API レベル 28)以降では、ビューが暗黙的にフォーカスを受け取ることはないため、フォーカスされていることは重要な前提条件です。
フォーカスに関するおすすめの方法
ロータリー入力イベントに応答するには、スクロール可能なコンテナがフォーカスされている必要があります。
ロータリー入力イベントによってビュー階層が上に移動することはありません。フォーカスされているビューがない場合、またはフォーカスされているビューが View.onGenericMotionEvent()
から false
を返す場合、イベントは Activity.onGenericMotionEvent()
に送信されます。
ロータリー入力イベントへの応答に関するおすすめの方法は次のとおりです。
- デフォルトでは、アクティビティを起動しても、またはビューをタップしても、ビューは(フォーカス可能であっても)フォーカスされないことに注意してください。ビューがフォーカスされるようにするには、ビューで
<requestFocus />
タグを使用するか、手動でView.requestFocus()
を呼び出す必要があります。 android:focusable="true"
とandroid:focusableInTouchMode="true"
の両方を使用して、スクロール可能なカスタムビューをフォーカス可能としてマークします。- スクロール可能なビューが
Activity.onCreate()
の後にアタッチされる場合(たとえば、UI を構築する前にネットワーク リクエストが終了するのを待機する場合)は、ビューがアタッチされた後にrequestFocus()
を呼び出します。 - スクロール可能なビューが初期段階で
INVISIBLE
またはGONE
であった場合は、VISIBLE
に設定する際にrequestFocus()
を呼び出します。 - アクティビティにスクロール可能なビューが複数含まれている場合は、
<requestFocus />
タグでフォーカスするビューを 1 つ選択します。回転するサイドボタンでは、ネストされたスクロールはサポートされていません。 - ユーザーが操作したときにフォーカスを受け取る他のビュー(
InputText
など)が UI に含まれている場合は、フォーカスを失ったときにスクロール可能なビューにフォーカスを復元する方法をユーザーに示します。これを行うには、スクロール可能なビューのタップをリッスンし、タップされたときにrequestFocus()
を呼び出します。
カスタムのローテーション動作
スクロール可能なビューがロータリー入力スクロールをネイティブにサポートしていない場合や、スクロール以外の目的でロータリー入力を使用する場合(ズームイン / ズームアウト、ダイヤルの回転など)は、スクロール イベントをご自分で処理できます。必ずビューがフォーカスされるように設定してください。そのように設定しないと、イベントは発生しません。
次のコード スニペットは、MotionEvent
、InputDeviceCompat
、ViewConfigurationCompat
を使用してカスタム スクロールをビューに追加する方法を示しています。
Kotlin
myView.setOnGenericMotionListener { v, ev -> if (ev.action == MotionEvent.ACTION_SCROLL && ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER) ) { // Don't forget the negation here val delta = -ev.getAxisValue(MotionEventCompat.AXIS_SCROLL) * ViewConfigurationCompat.getScaledVerticalScrollFactor( ViewConfiguration.get(context), context ) // Swap these axes to scroll horizontally instead v.scrollBy(0, delta.roundToInt()) true } else { false } }
Java
myView.setOnGenericMotionListener(new View.OnGenericMotionListener() { @Override public boolean onGenericMotion(View v, MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_SCROLL && ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER) ) { // Don't forget the negation here float delta = -ev.getAxisValue(MotionEventCompat.AXIS_SCROLL) * ViewConfigurationCompat.getScaledVerticalScrollFactor( ViewConfiguration.get(context), context ); // Swap these axes to scroll horizontally instead v.scrollBy(0, Math.round(delta)); return true; } return false; } });
エミュレータを使用してテストする
Wear デバイス上のロータリー入力スクロールをシミュレートするには、Android Emulator を使用します。そのためには、プロジェクトを実行するエミュレータで Wear アプリを起動するか、APK ファイルをエミュレータにドラッグしてインストールします。
エミュレータでロータリー入力をテストする手順は次のとおりです。
- SDK Manager の [SDK Tools] タブで、Android Emulator 26.0.3 以降を入手します。
- Android Studio で、[Tools] > [Android] > [AVD Manager] を選択します。 API 25 以降を使用して新しい Wear デバイスを作成します。
- Android Studio からエミュレータを実行します。
- エミュレータ ツールバーの下部にあるオーバーフロー メニュー(3 つの点)をクリックします。新しいウィンドウで [Rotary input] タブをクリックしてロータリー入力インターフェースを開き、ロータリー入力のスクロールを試みます。
次の動画は、エミュレータでのロータリー入力を示しています。