Cómo salir de las actividades de pantalla completa en Wear

Para salir de una actividad de Wear OS, el usuario puede deslizar el dedo de izquierda a derecha. Si la app tiene desplazamiento horizontal, el usuario puede salir de ella navegando hacia el borde del contenido y deslizando el dedo de izquierda a derecha. Si el usuario presiona el botón de encendido, regresará a la cara del reloj.

Gesto de deslizar para descartar

Los usuarios deslizan el dedo de izquierda a derecha para cerrar la pantalla actual. Por lo tanto, te recomendamos usar lo siguiente:

  • Diseños verticales
  • Contenedores de contenido

Además, recomendamos que tu app no contenga gestos de deslizamiento horizontales.

Cómo descartar una actividad

Las actividades admiten automáticamente el gesto de deslizar para descartar. Si se desliza una actividad de izquierda a derecha, se produce un rechazo, y la app navega hacia la pila de actividades.

Cómo descartar un fragmento

Para admitir el gesto de deslizar para descartar en fragmentos, debes unir la vista que contiene el fragmento con la clase SwipeDismissFrameLayout. Ten esto en cuenta cuando decidas si usar fragmentos o no. Usa la clase SwipeDismissFrameLayout como se muestra en el siguiente ejemplo:

Kotlin

class SwipeDismissFragment : Fragment() {
    private val callback = object : SwipeDismissFrameLayout.Callback() {
        override fun onSwipeStarted(layout: SwipeDismissFrameLayout) {
            // Optional
        }

        override fun onSwipeCanceled(layout: SwipeDismissFrameLayout) {
            // Optional
        }

        override fun onDismissed(layout: SwipeDismissFrameLayout) {
            // Code here for custom behavior, such as going up the
            // back stack and destroying the fragment but staying in the app.
        }
    }

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View =
            SwipeDismissFrameLayout(activity).apply {

                // If the fragment should fill the screen (optional), then in the layout file,
                // in the androidx.wear.widget.SwipeDismissFrameLayout element,
                // set the android:layout_width and android:layout_height attributes
                // to "match_parent".

                inflater.inflate(
                        R.layout.swipe_dismiss_frame_layout,
                        this,
                        false
                ).also { inflatedView ->
                    addView(inflatedView)
                }
                addCallback(callback)
            }
}

Java

public class SwipeDismissFragment extends Fragment {
  private final Callback callback =
    new Callback() {
      @Override
        public void onSwipeStart() {
          // Optional
        }

        @Override
        public void onSwipeCancelled() {
          // Optional
        }

        @Override
        public void onDismissed(SwipeDismissFrameLayout layout) {
          // Code here for custom behavior, such as going up the
          // back stack and destroying the fragment but staying in the app.
        }
      };

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    SwipeDismissFrameLayout swipeLayout = new SwipeDismissFrameLayout(getActivity());

    // If the fragment should fill the screen (optional), then in the layout file,
    // in the androidx.wear.widget.SwipeDismissFrameLayout element,
    // set the android:layout_width and android:layout_height attributes
    // to "match_parent".

    View inflatedView = inflater.inflate(R.layout.swipe_dismiss_frame_layout, swipeLayout, false);
    swipeLayout.addView(inflatedView);
    swipeLayout.addCallback(callback);

    return swipeLayout;
    }
}

Nota: Cuando uses fragmentos dentro de tu actividad, usa FragmentManager.add en lugar de FragmentManager.replace para admitir el gesto de deslizar para descartar. De esta manera, te aseguras de que tu fragmento se renderiza en los fragmentos superiores mientras se desliza.

Vistas horizontales desplazables

En algunos casos, como en una vista que contiene un mapa que admite el desplazamiento lateral, la interfaz de usuario no puede evitar el deslizamiento horizontal. En este escenario, hay dos opciones:

  • Si la pila de actividades es corta, el usuario puede descartar la app y volver a la pantalla principal de la cara de reloj con el botón de encendido.
  • Si deseas que el usuario baje por la pila de actividades, puedes ajustar la vista en un objeto SwipeDismissFrameLayout, que admite el deslizamiento en el borde. Este tipo de desplazamiento se habilita cuando la vista o sus elementos secundarios muestran un valor true de una llamada canScrollHorizontally(). El deslizamiento en el borde permite al usuario descartar la vista con solo deslizar el dedo desde el 10% del extremo izquierdo de la pantalla, en lugar de tener que hacerlo en cualquier lugar de la vista.

En los siguientes ejemplos, se muestra cómo unir una vista a un objeto SwipeDismissFrameLayout:

<androidx.wear.widget.SwipeDismissFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/swipe_dismiss_root" >

    <TextView
        android:id="@+id/test_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Swipe me to dismiss me." />
</androidx.wear.widget.SwipeDismissFrameLayout>

Kotlin

activity?.findViewById<SwipeDismissFrameLayout>(R.id.swipe_dismiss_root)?.apply {
    addCallback(object : SwipeDismissFrameLayout.Callback() {

        override fun onDismissed(layout: SwipeDismissFrameLayout) {
            layout.visibility = View.GONE
        }
    })
}

Java

SwipeDismissFrameLayout testLayout =
    (SwipeDismissFrameLayout) activity.findViewById(R.id.swipe_dismiss_root);
testLayout.addCallback(new SwipeDismissFrameLayout.Callback() {
    @Override
    public void onDismissed(SwipeDismissFrameLayout layout) {
        layout.setVisibility(View.GONE);
    }
  }
);

No recomendado: Inhabilitar el gesto de deslizar para descartar

Por lo general, no recomendamos inhabilitar el gesto de deslizar para descartar porque el usuario espera descartar cualquier pantalla con solo deslizar el dedo. En un caso excepcional, puedes ampliar el tema predeterminado de un recurso de estilo y configurar el atributo android:windowSwipeToDismiss en false, como figura en la siguiente muestra de código:

<resources>
  <style name="AppTheme" parent="@android:style/Theme.DeviceDefault">
    <item name="android:windowSwipeToDismiss">false</item>
  </style>
</resources>

Luego, puedes informarles a los usuarios (en el primer uso de la app) que pueden salir de ella presionando el botón de encendido.

Cómo descartar con el botón de encendido

Cuando presionas el botón de encendido, se envía un evento de la tecla de encendido. Por lo tanto, no puedes utilizar el botón de encendido como botón de retroceso o para la navegación en general.

Cuando se presiona el botón de encendido, el usuario regresa a la pantalla principal de la cara del reloj. Hay dos excepciones:

  • Si el usuario es un Editor de método de entrada (IME), por ejemplo, una pantalla de reconocimiento de escritura a mano, cuando se presiona el botón, se cierra el IME y el usuario regresa a la app.
  • Si el usuario está en la cara del reloj, cuando presiona el botón de hardware, se abre el selector de apps.

Nota: Cuando se presiona el botón de encendido, el método isFinishing() de la clase Activity no muestra true, y no puedes interceptar el evento clave.

Para obtener más información, consulta Navigation.