Quitter les activités en plein écran sur Wear

Un utilisateur peut quitter une activité Wear OS en balayant l'écran de gauche à droite. Si l'appli possède un défilement horizontal, l'utilisateur peut la quitter en accédant au bord du contenu, puis en balayant l'écran de gauche à droite. Il peut aussi appuyer sur le bouton March/Arrêt pour revenir au cadran de la montre.

Geste Balayer pour fermer

Les utilisateurs balayent l'écran de gauche à droite pour fermer l'écran actuel. Pour cette raison, nous vous recommandons les éléments suivants :

  • Mises en page verticales
  • Conteneurs

Nous vous recommandons aussi de ne pas intégrer de gestes de balayage horizontal à votre application.

Fermer une activité

Les activités prennent automatiquement en charge le geste Balayer pour fermer. Effectuer un balayage de gauche à droite sur une activité permet de la fermer. L'application descend alors dans la pile "Retour".

Fermer un fragment

Pour prendre en charge le geste Balayer pour fermer dans des fragments, vous devez encapsuler la vue contenant le fragment dans la classe SwipeDismissFrameLayout. Prenez ce point en considération lorsque vous décidez d'utiliser ou non les fragments. Servez-vous de la classe SwipeDismissFrameLayout, comme illustré dans l'exemple suivant :

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

Remarque : Lorsque vous utilisez des fragments au sein de votre activité, servez-vous de FragmentManager.add plutôt que de FragmentManager.replace pour prendre en charge le geste Balayer pour fermer. Cela permet de garantir que votre fragment précédent est affiché sous le segment supérieur lorsqu'il est balayé.

Vues déroulantes horizontales

Dans certains cas, par exemple dans une vue contenant une carte prenant en charge le mode panoramique, l'interface utilisateur peut empêcher le défilement horizontal. Dans ce cas, deux choix s'offrent à vous :

  • Si la pile "Retour" est courte, l'utilisateur peut fermer l'appli et revenir à l'écran d'accueil sur le cadran de la montre en appuyant sur le bouton Marche/Arrêt.
  • Si vous souhaitez que l'utilisateur descende dans la pile "Retour", vous pouvez encapsuler la vue dans un objet SwipeDismissFrameLayout, qui prend en charge le balayage en partant du bord. Le balayage en partant du bord est activé lorsque la vue ou ses enfants renvoient true depuis un appel canScrollHorizontally(). Le balayage en partant du bord permet à l'utilisateur de fermer la vue en effectuant un balayage depuis les 10 % de l'écran les plus à gauche, plutôt que depuis n'importe où dans la vue.

Les exemples suivants montrent comment encapsuler une vue dans un objet 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);
    }
  }
);

Déconseillé : désactiver Balayer pour fermer

En général, nous déconseillons de désactiver Balayer pour fermer, car l'utilisateur s'attend à pouvoir fermer n'importe quel écran à l'aide d'un balayage. De manière exceptionnelle, vous pouvez étendre le thème par défaut dans une ressource de style et définir l'attribut android:windowSwipeToDismiss sur false, comme illustré dans l'exemple de code suivant :

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

Vous pouvez ensuite informer les utilisateurs, lors de la première utilisation de votre application, qu'ils peuvent fermer l'application en appuyant sur le bouton Marche/Arrêt.

Fermeture avec le bouton Marche/Arrêt

L'appui sur le bouton Marche/Arrêt physique envoie un événement de touche Marche/Arrêt. Par conséquent, vous ne pouvez pas utiliser le bouton Marche/Arrêt en tant que bouton Retour ni pour la navigation en général.

Lorsqu'il appuie sur le bouton Marche/Arrêt, l'utilisateur revient à l'écran d'accueil du cadran de la montre. À noter toutefois les deux exceptions suivantes :

  • Si l'utilisateur se trouve dans un éditeur de mode de saisie (IME), par exemple l'écran de reconnaissance de l'écriture manuscrite, et qu'il appuie sur le bouton, l'IME se ferme et l'utilisateur est renvoyé vers l'application.
  • Si l'utilisateur se trouve sur le cadran de la montre et qu'il appuie sur le bouton physique, le lanceur d'applications s'ouvre.

Notez que lorsque vous appuyez sur le bouton Marche/Arrêt, la méthode isFinishing() de la classe Activity ne renvoie pas true, et vous pouvez intercepter l'événement clé.

Pour en savoir plus, consultez la section Navigation.