Some Wear OS devices contain a physical *rotating side button* . When the user turns the
button, it scrolls your app's current view up or down. This type of input is called
*rotary input*.

**Note:** This guide refers primarily to handling rotary input using
View-based UIs. For more information on handling rotary input using Compose for Wear OS, see
[Rotary input on Compose](https://developer.android.com/training/wearables/compose/rotary-input).

Many scrollable containers, like
[ScrollView](https://developer.android.com/reference/android/widget/ScrollView),
[ListView](https://developer.android.com/reference/android/widget/ListView),
[HorizontalScrollView](https://developer.android.com/reference/android/widget/HorizontalScrollView),
and [WearableRecyclerView](https://developer.android.com/reference/androidx/wear/widget/WearableRecyclerView),
support rotary input if they have focus without requiring any Wear
OS-specific code.
Having focus is an important prerequisite, because on Android 9 (API level
28) and higher, views don't implicitly receive focus.

## Focus best practices


To respond to rotary input events, a scrollable container must have focus.
Rotary input events don't bubble up the view
hierarchy. If there is no focused view, or if the focused view returns `false` from
[View.onGenericMotionEvent()](https://developer.android.com/reference/android/view/View#onGenericMotionEvent(android.view.MotionEvent)),
then the event is sent to
[Activity.onGenericMotionEvent()](https://developer.android.com/reference/android/app/Activity#onGenericMotionEvent(android.view.MotionEvent)).


The following are best practices around responding to rotary input events:

- Bear in mind that, by default, launching an activity or even tapping on a view does not give it focus, even if it is focusable. To give your view focus, the view must use the [&ltrequestFocus />](https://developer.android.com/guide/topics/resources/layout-resource) tag or manually call [View.requestFocus()](https://developer.android.com/reference/android/view/View#requestFocus()).
- Mark custom scrollable views as focusable using both `android:focusable="true"` and `android:focusableInTouchMode="true"`.
- If your scrollable view is attached after [Activity.onCreate()](https://developer.android.com/reference/android/app/Activity#onCreate(android.os.Bundle))---for example, waiting for a network request to finish before building your UI, call `requestFocus()` after attaching it.
- If your scrollable view is initially [INVISIBLE](https://developer.android.com/reference/android/view/View#INVISIBLE) or [GONE](https://developer.android.com/reference/android/view/View#GONE), call `requestFocus()` when you set it to [VISIBLE](https://developer.android.com/reference/android/view/View#VISIBLE).
- If your activity contains multiple scrollable views, choose one to focus using the [&ltrequestFocus />](https://developer.android.com/guide/topics/resources/layout-resource) tag. Nested scrolling is not supported with the rotating side button.
- If your UI contains some other view that takes focus when the user interacts with it---for example, an `InputText`, give the user a way to restore focus to the scrollable view if it loses focus by listening for taps on the scrollable view and calling `requestFocus()` in response.

## Custom rotating behavior

If your scrollable view doesn't natively support rotary input scrolling, or if you want to
use your rotary input for something other than scrolling---such as to
zoom in and out or to turn dials---you can handle the scroll events
yourself. Remember to make sure your view gains focus, otherwise
the events will not come through.

The following code snippet shows how to use [MotionEvent](https://developer.android.com/reference/android/view/MotionEvent),
[InputDeviceCompat](https://developer.android.com/reference/kotlin/androidx/core/view/InputDeviceCompat),
and [ViewConfigurationCompat](https://developer.android.com/reference/androidx/core/view/ViewConfigurationCompat)
to add custom scrolling to your view:  

### Kotlin

```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

```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;
  }
});
```

## Test using an emulator

Use the [Android Emulator](https://developer.android.com/studio/run/emulator#about) to simulate rotary input
scrolling on a Wear device. Launch your Wear app on the emulator to run
your project or drag an
APK file onto the emulator to install it.

To test the rotary input on the emulator:

1. From the [SDK manager](https://developer.android.com/tools/help/sdk-manager), use the **SDK tools** tab to get Android Emulator 26.0.3 or higher.
2. In Android Studio, select **Tools \>
   Android \> AVD Manager** . [Create a new Wear device](https://developer.android.com/studio/run/managing-avds#createavd) with API 25 or higher.
3. [Run the emulator from Android Studio](https://developer.android.com/studio/run/emulator#runningapp).
4. Click the three-dot overflow menu at the bottom of the emulator toolbar. Click the **Rotary input** tab in the new window to open the rotary input interface and try rotary input scrolling.

The following video shows rotary input in the emulator: