Zamknij pełny ekran na Wear

Wypróbuj metodę Compose
Jetpack Compose na Wear OS to zalecany zestaw narzędzi do tworzenia interfejsu Wear OS.

Użytkownik może zamknąć aktywność w Wear OS, przesuwając palcem od lewej do prawej. Jeśli aplikacja ma przewijanie w poziomie, użytkownik zamyka ją, przechodząc na krawędź treści, a następnie przesuwając palcem od lewej do prawej. Naciśnięcie przycisku zasilania również powoduje powrót do tarczy zegarka.

Gest przesuwania, aby zamknąć

Aby zamknąć bieżący ekran, użytkownicy przesuwają palcem od lewej do prawej. Dlatego zalecamy używanie tych elementów:

  • Układy pionowe
  • Kontenery treści

Zalecamy też, aby aplikacja nie zawierała gestów przesuwania w poziomie.

Odrzucanie aktywności

Aktywności automatycznie obsługują zamykanie przez przesunięcie. Przesunięcie aktywności od lewej do prawej powoduje jej zamknięcie, a aplikacja przechodzi do stosu wstecznego.

Zamykanie fragmentu

Aby obsługiwać zamykanie fragmentów przez przesunięcie, musisz umieścić widok zawierający fragment w klasie SwipeDismissFrameLayout. Weź to pod uwagę, gdy będziesz decydować, czy używać fragmentów. Użyj klasy SwipeDismissFrameLayout, jak pokazano w tym przykładzie:

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

Uwaga: jeśli w aktywności używasz fragmentów, używaj FragmentManager.add zamiast FragmentManager.replace w celu obsługi gestu zamykania przez przesunięcie. Dzięki temu poprzedni fragment będzie renderowany pod górnym fragmentem podczas przesuwania.

Widoki z możliwością przewijania w poziomie

W niektórych przypadkach, np. w widoku zawierającym mapę, którą można przesuwać, interfejs użytkownika nie może zapobiec przesuwaniu w poziomie. W takim przypadku masz 2 możliwości:

  • Jeśli stos wsteczny jest krótki, użytkownik może zamknąć aplikację i wrócić do ekranu głównego tarczy zegarka, naciskając przycisk zasilania.
  • Jeśli chcesz, aby użytkownik mógł przejść do poprzedniego ekranu, możesz umieścić widok w obiekcie SwipeDismissFrameLayout, który obsługuje przesuwanie od krawędzi. Przesunięcie od krawędzi jest włączone, gdy widok lub jego elementy podrzędne zwracają wartość true z wywołania canScrollHorizontally(). Przesunięcie od krawędzi pozwala użytkownikowi zamknąć widok, przesuwając palcem od lewej krawędzi ekranu (10% ekranu), a nie z dowolnego miejsca w widoku.

Poniższe przykłady pokazują, jak umieścić widok w obiekcie 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);
    }
  }
);

Niezalecane: wyłączenie zamykania przez przesunięcie

Zwykle nie zalecamy wyłączania funkcji zamykania gestem, ponieważ użytkownik oczekuje, że będzie mógł zamknąć dowolny ekran za pomocą gestu. W wyjątkowych przypadkach możesz rozszerzyć domyślny motyw w  zasobie stylu i ustawić atrybut android:windowSwipeToDismiss na false, jak pokazano w tym przykładowym kodzie:

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

Następnie możesz poinformować użytkowników, że przy pierwszym użyciu aplikacji mogą ją zamknąć, naciskając przycisk zasilania.

Zamykanie za pomocą przycisku zasilania

Naciśnięcie fizycznego przycisku zasilania powoduje wysłanie zdarzenia klawisza zasilania. Nie możesz więc używać przycisku zasilania jako przycisku Wstecz ani do nawigacji.

Po naciśnięciu przycisku zasilania użytkownik wraca do ekranu głównego tarczy zegarka. Istnieją dwa wyjątki:

  • Jeśli użytkownik korzysta z edytora metody wprowadzania (IME), np. ekranu rozpoznawania pisma odręcznego, naciśnięcie przycisku zamyka edytor IME i wraca do aplikacji.
  • Jeśli użytkownik jest na tarczy zegarka, naciśnięcie przycisku na urządzeniu otwiera menu z aplikacjami.

Pamiętaj, że po naciśnięciu przycisku zasilania metoda isFinishing() klasy Activity nie zwraca wartości true i nie można przechwycić zdarzenia naciśnięcia klawisza.

Więcej informacji znajdziesz w sekcji Nawigacja.