Interação giratória

Alguns dispositivos Wear OS têm um botão lateral giratório. Quando o usuário gira o botão, a visualização atual do app rola para cima ou para baixo. Esse tipo de ação é chamada de entrada por seletor giratório.

Observação: este guia se refere principalmente ao processamento da entrada por seletor giratório usando interfaces baseadas em visualização. Para mais informações sobre como processar entradas por seletor giratório usando o Compose para Wear OS, consulte Entrada por seletor giratório no Compose.

Vários contêineres roláveis, como ScrollView, ListView, HorizontalScrollView e WearableRecyclerView, oferecem suporte à entrada por seletor giratório desde que o foco seja definido sem exigir nenhum código específico do Wear OS. Estar em foco é um pré-requisito importante porque, no Android 9 (nível 28 da API) e versões mais recentes, as visualizações não recebem foco de maneira implícita.

Práticas recomendadas de foco

Para responder a eventos de entrada por seletor giratório, um contêiner rolável precisa estar em foco. Os eventos de entrada por seletor giratório não aparecem na hierarquia de visualização. Se não houver uma visualização em foco ou se ela retornar false de View.onGenericMotionEvent(), o evento é enviado para Activity.onGenericMotionEvent().

Confira abaixo as práticas recomendadas para responder a eventos de entrada por seletor giratório:

  • Não esqueça que, por padrão, iniciar uma atividade ou até mesmo tocar em uma visualização não a coloca em foco, mesmo que ela seja focalizável. Para que a visualização entre em foco, ela precisa usar a tag <requestFocus /> ou chamar View.requestFocus() manualmente.
  • Marque as visualizações roláveis personalizadas como focalizáveis usando android:focusable="true" e android:focusableInTouchMode="true".
  • Se a visualização rolável for anexada depois de Activity.onCreate(), por exemplo, se você esperar que uma solicitação de rede seja concluída antes de criar a interface, chame requestFocus() depois de anexá-la.
  • Se a visualização rolável inicialmente for INVISIBLE ou GONE, você precisará chamar requestFocus() quando definir como VISIBLE.
  • Caso a atividade contenha várias visualizações roláveis, escolha uma para focalizar usando a tag <requestFocus />. O botão lateral giratório não oferece suporte à rolagem aninhada.
  • Se a interface tiver outra visualização que roube o foco quando o usuário interagir com ela, por exemplo, um InputText, ofereça uma maneira de restaurar o foco para a visualização rolável, se necessário. Detecte os toques na visualização rolável e chame requestFocus() em resposta.

Comportamento de rolagem personalizado

Caso a visualização rolável não ofereça suporte nativo à rolagem de entrada por seletor giratório ou caso você queira usar essa entrada para fazer algo que não seja uma rolagem (como aumentar/diminuir o zoom ou interagir com seletores), você pode processar os eventos de rolagem por conta própria. É importante garantir que a visualização receba foco, caso contrário, os eventos não serão transmitidos.

O snippet de código a seguir mostra como usar MotionEvent, InputDeviceCompat e ViewConfigurationCompat para adicionar rolagem personalizada à visualização:

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

Testar usando um emulador

Use o Android Emulator para simular a rolagem de entrada por seletor giratório em um dispositivo Wear. Inicie o app para Wear no emulador ao executar seu projeto ou arraste um arquivo APK para o emulador para instalá-lo.

Para testar a entrada por seletor giratório no emulador:

  1. No SDK Manager, use a guia SDK Tools para instalar o Android Emulator 26.0.3 ou versões mais recentes.
  2. No Android Studio, selecione Tools > Android > AVD Manager. Crie um novo dispositivo Wear com o nível 25 da API ou mais recente.
  3. Execute o emulador no Android Studio.
  4. Clique no menu flutuante de três pontos na parte de baixo da barra de ferramentas do emulador. Clique na guia Rotary input na nova janela para abrir a interface de entrada por seletor giratório e tente rolar o seletor.

O vídeo a seguir mostra a entrada por seletor giratório no emulador: