Wear のロータリー入力

一部の Wear OS デバイスはロータリー入力(回転サイドボタン(RSB)など)をサポートしています。ユーザーがボタンを回すと、アプリの現在のビューが上または下にスクロールします。

アプリ内で ScrollViewListViewHorizontalScrollViewWearableRecyclerView のいずれかを使用している場合、アプリのビューはデフォルトでロータリー入力をサポートします。上記以外のカスタムビューを使用している場合や、ロータリー入力イベントを手動で処理する必要がある場合は、カスタムのロータリー入力スクロールを追加するをご覧ください。

以下の関連リソースをご覧ください。

フォーカスに関するおすすめの方法

ロータリー入力イベントに応答するには、スクロール ビューがフォーカスされている必要があります。ほとんどの場合、これは自動的に行われます。Activity を作成するとすぐに、スクロール ビューがフォーカスされます。ただし、以下のような状況では、アプリのビューのフォーカスを手動で処理する必要があります。

  • Activity.onCreate() の後にスクロール可能なビューがアタッチされる場合(たとえば、UI を構築する前にネットワーク リクエストが終了するのを待機する場合)は、ビューがアタッチされた後で requestFocus を呼び出す必要があります。
  • スクロール可能なビューが最初は INVISIBLE または GONE である場合、VISIBLE に設定する際に requestFocus を呼び出す必要があります。
  • アクティビティにスクロール可能なビューが複数含まれている場合(たとえば、ネストされたスクロールを使用している場合)は、1 つのビューを選択する必要があります(通常は <requestFocus /> タグで選択します)。現在、RSB のスクロールでは、ネストされたスクロールはサポートされていません。
  • ユーザーが操作したときにフォーカスを奪うビューが UI に含まれている場合(まれなケースですが、最も一般的な例は InputText です)、スクロール可能なビューがフォーカスを失ったときにフォーカスを取り戻すなんらかの方法をユーザーに提供する必要があります。そのための方法として、通常はスクロール可能なビューのタップをリッスンし、タップされたときに requestFocus を呼び出します。

カスタムのロータリー入力スクロールを追加する

スクロール可能なビューがロータリー入力スクロールをネイティブにサポートしていない場合、またはロータリー入力イベント(拡大 / 縮小、ダイヤルを回すなど)に応じてスクロール以外の動作を行う必要がある場合は、ウェアラブル サポート ライブラリRotaryEncoder メソッドを使用できます。

次のコード スニペットは、RotaryEncoder を使用してカスタム スクロールをアプリのビューに追加する方法を示しています。

Kotlin

    myView.setOnGenericMotionListener(View.OnGenericMotionListener { v, ev ->
        if (ev.action == MotionEvent.ACTION_SCROLL && RotaryEncoder.isFromRotaryEncoder(ev)) {
            // Don't forget the negation here
            val delta = -RotaryEncoder.getRotaryAxisValue(ev) *
                    RotaryEncoder.getScaledScrollFactor(context)

            // Swap these axes if you want to do horizontal scrolling instead
            v.scrollBy(0, Math.round(delta))

            return@OnGenericMotionListener true
        }

        false
    })
    

Java

    myView.setOnGenericMotionListener(new View.OnGenericMotionListener() {
        @Override
        public boolean onGenericMotion(View v, MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_SCROLL && RotaryEncoder.isFromRotaryEncoder(ev)) {
                // Don't forget the negation here
                float delta = -RotaryEncoder.getRotaryAxisValue(ev) * RotaryEncoder.getScaledScrollFactor(
                getContext());

                // Swap these axes if you want to do horizontal scrolling instead
                v.scrollBy(0, Math.round(delta));

                return true;
            }

            return false;
        }
    });
    

エミュレータでロータリー入力ボタンをテストする

Android Emulator を使用すると、Wear デバイスでロータリー入力スクロールをシミュレートできます。そのためには、プロジェクトを実行するときにエミュレータで Wear アプリを起動するか、APK ファイルをエミュレータにドラッグしてインストールします。

エミュレータでロータリー入力をテストする手順は次のとおりです。

  1. SDK Manager の [SDK tools] タブで、Android Emulator 26.0.3 以上を入手します。
  2. API 25 を使用して AVD(Android Virtual Device)を作成します。

    Studio で、[Tools] > [Android] > [AVD Manager] を選択します。 API 25 を使用して新しい Wear デバイスを作成します。

  3. Android Studio からエミュレータを実行します。
  4. ロータリー入力スクロールを試します。

    オーバーフロー ボタン(エミュレータ ツールバーの下部にある 3 つの点)をクリックします。次に、新しいウィンドウで [Rotary input] タブをクリックして、ロータリー入力インターフェースを開きます。

次の動画は、エミュレータでのロータリー入力を示しています。

フォーカスの動作に関するヒント

  • Android 9(API レベル 28)以降では、ビューは暗黙的にフォーカスを受け取らないため、明示的にフォーカスを受け取る必要があります。
  • スクロール可能なビューは、android:focusable="true"android:focusableInTouchMode="true" の両方を使用して、フォーカス可能なビューとして登録する必要があります。
  • デフォルトでは、アクティビティを起動しても、またはビューをタップしても、ビューは(フォーカス可能であっても)フォーカスされません。ビューがフォーカスされるようにするには、ビューで <requestFocus /> タグを使用するか、または手動で View.requestFocus() を呼び出す必要があります。
  • ロータリー入力イベントは、フォーカスされているビューにのみ送信されます。このイベントによってビュー階層が上に移動することはありません。フォーカスされているビューがない場合、またはフォーカスされているビューが View.onGenericMotionEvent から false を返す場合にのみ、イベントは Activity.onGenericMotionEvent に送信されます。