로터리 입력

일부 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 /> 태그를 통해 포커스를 둘 뷰를 선택합니다. 중첩 스크롤은 측면 회전 버튼에서 지원되지 않습니다.
  • 사용자가 UI와 상호작용할 때 포커스를 가져가는 다른 뷰가 UI에 포함되어 있다면(예: InputText) 스크롤 가능한 뷰가 포커스를 잃을 경우 스크롤 가능한 뷰에서 탭을 리슨하고 응답으로 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;
  }
});

에뮬레이터를 사용하여 테스트

Android Emulator를 사용하여 Wear 기기에서 로터리 입력 스크롤을 시뮬레이션합니다. 에뮬레이터에서 Wear 앱을 실행하여 프로젝트를 실행하거나 APK 파일을 에뮬레이터로 드래그하여 설치합니다.

에뮬레이터에서 로터리 입력을 테스트하려면 다음을 따르세요.

  1. SDK ManagerSDK Tools 탭에서 Android Emulator 26.0.3 이상을 가져옵니다.
  2. Android 스튜디오에서 Tools > Android > AVD Manager를 선택합니다. API 25 이상으로 새 Wear 기기를 만듭니다.
  3. Android 스튜디오에서 에뮬레이터를 실행합니다.
  4. 에뮬레이터 툴바 하단에서 점 3개로 된 더보기 메뉴를 클릭합니다. 새 창에서 Rotary input 탭을 클릭하여 로터리 입력 인터페이스를 열고 로터리 입력 스크롤을 시도합니다.

다음 동영상은 에뮬레이터에서의 로터리 입력을 보여줍니다.