Cómo usar gestos de muñeca en Wear

Cuando no es conveniente usar una pantalla táctil, los gestos de la muñeca pueden permitir interacciones rápidas con una mano en tu app.

Por ejemplo, un usuario puede desplazarse por las notificaciones con una mano mientras sostiene una taza de agua con la otra. Los ejemplos que muestran el uso de gestos de la muñeca también incluyen lo siguiente:

  • En una app para trotar, navegar a través de pantallas verticales que muestran los pasos dados, el tiempo transcurrido y el ritmo actual
  • En un aeropuerto con equipaje, desplazarse por la información sobre el vuelo y la puerta
  • Desplazarse a través de artículos de noticias

Para revisar los gestos de la muñeca en el reloj, confirma que estén activados seleccionando Configuración > Gestos > Gestos de muñeca Activados. Luego, completa el instructivo sobre Gestos en el reloj (Configuración > Gestos > Iniciar instructivo).

El siguiente gesto de la Ayuda para Wear OS no está disponible para apps:

  • Sacudir la muñeca

Los gestos de muñeca se pueden utilizar de las siguientes maneras:

Cada gesto de muñeca se asigna a una constante int de la clase KeyEvent, como se muestra en la siguiente tabla:

Gesto KeyEvent Descripción
Gira la muñeca hacia afuera rápidamente KEYCODE_NAVIGATE_NEXT Esta clave de código va al siguiente elemento.
Gira la muñeca hacia adentro rápidamente KEYCODE_NAVIGATE_PREVIOUS Esta clave de código va al elemento anterior.

Usa un diseño curvo que sea compatible con los gestos de muñeca

La clase WearableRecyclerView proporciona un diseño curvo para las listas y admite automáticamente los gestos de muñeca. Tiene acciones predefinidas para casos de gestos de muñeca cuando la Vista tiene el enfoque. Para obtener información sobre el uso de la clase WearableRecyclerView, consulta Cómo crear listas, y las Prácticas recomendadas.

Nota: La clase WearableRecyclerView reemplaza una clase obsoleta similar en la biblioteca de compatibilidad para wearables.

Incluso si usas un WearableRecyclerView, es posible que quieras usar constantes de la clase KeyEvent. Las acciones predefinidas se pueden anular subclasificando WearableRecyclerView y volviendo a implementar la devolución de llamada onKeyDown(). El comportamiento se puede inhabilitar por completo mediante setEnableGestureNavigation(false). También consulta Cómo controlar las acciones del teclado.

Cómo usar directamente eventos clave

Puedes usar eventos clave fuera de WearableRecyclerView para activar nuevas acciones en respuesta a eventos gestuales. Es importante destacar lo siguiente sobre estos gestos de eventos:

  • Se reconocen cuando un dispositivo está en modo activo.
  • Se entregan de la misma manera que todos los eventos clave.

Específicamente, estos eventos se entregan a la Actividad superior, a la Vista con enfoque de teclado. Al igual que cualquier otro evento clave, una clase que se relaciona con la interacción del usuario (como una Vista o una Actividad) que implementa KeyEvent.Callback puede escuchar eventos clave relacionados con los gestos de muñeca. El framework de Android llama a la vista o actividad que se centra en los eventos clave. para gestos, se llama al método onKeyDown() de devolución de llamadas cuando se producen gestos.

Como ejemplo, una app puede anular acciones predefinidas en una Vista o Actividad (ambas implementando KeyEvent.Callback) de la siguiente manera:

Kotlin

    class GesturesActivity : Activity() {

        /* KeyEvent.Callback */
        override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
            return when (keyCode) {
                KeyEvent.KEYCODE_NAVIGATE_NEXT ->
                    // Do something that advances a user View to the next item in an ordered list.
                    moveToNextItem()
                KeyEvent.KEYCODE_NAVIGATE_PREVIOUS ->
                    // Do something that advances a user View to the previous item in an ordered list.
                    moveToPreviousItem()
                else -> {
                    // If you did not handle it, let it be handled by the next possible element as deemed
                    // by the Activity.
                    super.onKeyDown(keyCode, event)
                }
            }
        }

        /** Shows the next item in the custom list.  */
        private fun moveToNextItem(): Boolean {
            …
            // Return true if handled successfully, otherwise return false.
            return false
        }

        /** Shows the previous item in the custom list.  */
        private fun moveToPreviousItem(): Boolean {
            …
            // Return true if handled successfully, otherwise return false.
            return false
        }
    }
    

Java

    public final class GesturesActivity extends Activity {

     @Override /* KeyEvent.Callback */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
      switch (keyCode) {
       case KeyEvent.KEYCODE_NAVIGATE_NEXT:
        // Do something that advances a user View to the next item in an ordered list.
        return moveToNextItem();
       case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:
        // Do something that advances a user View to the previous item in an ordered list.
        return moveToPreviousItem();
      }
      // If you did not handle it, let it be handled by the next possible element as deemed by the Activity.
      return super.onKeyDown(keyCode, event);
     }

     /** Shows the next item in the custom list. */
     private boolean moveToNextItem() {
      boolean handled = false;
      …
      // Return true if handled successfully, otherwise return false.
      return handled;
     }

     /** Shows the previous item in the custom list. */
     private boolean moveToPreviousItem() {
      boolean handled = false;
      …
      // Return true if handled successfully, otherwise return false.
      return handled;
     }
    }
    

Prácticas recomendadas

  • Revisa las páginas KeyEvent y KeyEvent.Callback para la entrega de eventos clave a tu Vista y Actividad.
  • Mantén una disposición direccional coherente:
    • Usa "Gira la muñeca hacia fuera" para el siguiente o "Gira la muñeca hacia adentro" para el anterior
  • Ten un toque paralelo para un gesto.
  • Proporciona información visual.
  • No utilices una clave de código con el fin de implementar una funcionalidad que sea contraintuitiva para el resto del sistema. Por ejemplo, no uses KEYCODE_NAVIGATE_NEXT para cancelar una acción o navegar el eje de izquierda a derecha con movimientos rápidos.
  • No interceptes los eventos clave en elementos que no forman parte de la interfaz de usuario, como, las Vistas que están fuera de la pantalla o parcialmente cubiertas. Es lo mismo que cualquier otro evento clave.
  • No reinterpretes los gestos de movimientos repetidos en el gesto nuevo. Puede entrar en conflicto con el gesto "Agitando la muñeca" del sistema.
  • Para que una vista reciba eventos clave de gestos, debe tener enfoque. consulta View::setFocusable(). Debido a que los gestos se tratan como eventos clave, activan una transición del "Modo táctil" que puede hacer cosas inesperadas. Por lo tanto, dado que los usuarios pueden alternar entre usar el tacto y los gestos, es necesario usar el método View::setFocusableInTouchmode(). En algunos casos, también puede ser necesario usar setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS) para que, cuando cambie el enfoque después del cambio al o del "Modo táctil" a la Vista prevista.
  • Usa requestFocus() y clearFocus() con cuidado:
    • Cuando llames a requestFocus(), asegúrate de que realmente se enfoque. Si la Vista está fuera de la pantalla, o está cubierta por otra Vista, podrían generarse acciones inesperadas cuando los gestos activen las devoluciones de llamada.
    • clearFocus() inicia una búsqueda de enfoque para encontrar otra vista adecuada. Según la jerarquía de Vistas, esta búsqueda puede requerir cálculos no triviales. También puede terminar asignando el enfoque a una Vista inesperada.
  • Los eventos clave se envían primero a la Vista enfocada en la jerarquía de Vistas. Si la vista enfocada no controla el evento (es decir, muestra false), el evento no se entrega a la vista superior, incluso si puede recibir el foco y tener un KeyListener. En su lugar, el evento se entrega a la Actividad actual manteniendo la jerarquía de Vistas enfocadas. Por lo tanto, puede ser necesario capturar todos los eventos en el nivel superior y luego pasar los códigos relevantes hacia abajo. Como alternativa, puedes subclasificar la actividad y anular el método dispatchKeyEvent(KeyEvent event) para asegurarte de que las claves se intercepten cuando sea necesario o se controlen cuando no se controlan en capas inferiores.