Dodano obsługę gestu przewidywanego przejścia wstecz

Rysunek 1. Mockup przewidującego gestu wstecz na telefonie

Przejście wstecz na podstawie przewidywania to funkcja nawigacji za pomocą gestów, która pozwala użytkownikom wyświetlić podgląd miejsca, do którego doprowadzi ich gest przesunięcia wstecz.

Na przykład gest wstecz może wyświetlić animowany podgląd ekranu głównego za aplikacją, jak pokazano na makiecie na rysunku 1.

Od wersji 15 Androida opcja dla deweloperów dotycząca przewidujących animacji wstecz nie jest już dostępna. Animacje systemowe, takie jak animacje przejścia do ekranu głównego, animacje przejścia między zadaniami i animacje przejścia między aktywnościami, są teraz wyświetlane w aplikacjach, które korzystają z przewidywanego gestu wstecz, niezależnie od tego, czy jest on włączony całkowicie, czy tylko na poziomie aktywności.

Możesz przetestować tę animację powrotu do strony głównej (jak opisano w następnej sekcji tej strony).

Obsługa przewidującego gestu wstecz wymaga zaktualizowania aplikacji przy użyciu kompatybilnego wstecz interfejsu OnBackPressedCallback AppCompat 1.6.0-alpha05 (AndroidX) lub nowszego albo nowego interfejsu OnBackInvokedCallback platformy. Większość aplikacji korzysta z interfejsu AndroidX API zgodnego ze starszymi wersjami.

Ta aktualizacja zapewnia ścieżkę migracji, która umożliwia prawidłowe przechwytywanie przekierowań wstecz. Polega ona na zastąpieniu przechwytywania wstecz z interfejsu KeyEvent.KEYCODE_BACK i wszystkich klas z metodami onBackPressed, takimi jak ActivityDialog, nowymi interfejsami API systemu Back.

Filmy z Codelab i Google I/O

Oprócz korzystania z tej dokumentacji na tej stronie wypróbuj nasze ćwiczenia z programowania. Udostępnia ono implementację WebView obsługującą przewidujący gest wstecz za pomocą interfejsów Activity API z AndroidX.

Możesz też obejrzeć nasz film z Google I/O, który zawiera dodatkowe przykłady implementacji interfejsów API AndroidX i platformy.

Zaktualizuj aplikację, która używa domyślnej nawigacji wstecz

Domyślnie włączone jest przewidywanie cofnięcia.

Jeśli Twoja aplikacja używa fragmentów lub komponentu nawigacji, zaktualizuj też AndroidX Activity 1.6.0-alpha05 lub nowszą wersję.

Aktualizacja aplikacji, która korzysta z niestandardowej nawigacji wstecz

Jeśli aplikacja implementuje niestandardowe zachowanie przy wciśnięciu przycisku Wstecz, dostępne są różne ścieżki migracji w zależności od tego, czy aplikacja korzysta z AndroidX i jak obsługuje nawigację wstecz.

Twoja aplikacja używa AndroidX Jak aplikacja obsługuje przekierowanie wstecz Zalecane rozwiązanie migracji (link na tej stronie)
Tak Interfejsy API AndroidX Migracja istniejącej implementacji AndroidX back
Nieobsługiwane interfejsy API platformy Przejście z aplikacji AndroidX zawierającej nieobsługiwane interfejsy API nawigacji wstecz na interfejsy API AndroidX
Nie Interfejsy API platformy, które można przenieść, ale nie są obsługiwane Przejście z interfejsów API aplikacji korzystających z nieobsługiwanych interfejsów API nawigacji wstecz na interfejsy API platformy
Nieobsługiwane interfejsy API platformy, których nie można przenieść Tymczasowo zrezygnuj z tego uprawnienia, ustawiając atrybut android:enableOnBackInvokedCallback na false w tagu <application> lub <activity> w pliku AndroidManifest.xml aplikacji.

Migracja implementacji przechodzenia wstecz w AndroidX

Ten przypadek użycia jest najczęstszy (i najbardziej zalecany). Dotyczy to nowych lub istniejących aplikacji, które implementują niestandardowe obsługę nawigacji za pomocą gestów za pomocą OnBackPressedDispatcher, zgodnie z opisem w artykule Niestandardowa nawigacja wstecz.

Aby zapewnić płynne działanie interfejsów API, które już korzystają z OnBackPressedDispatcher (takich jak fragmenty i komponent nawigacji), z użyciem przewidującego gestu wstecz, zaktualizuj do AndroidX Activity 1.6.0-alpha05.

```xml
// In your build.gradle file:
dependencies {

// Add this in addition to your other dependencies
implementation "androidx.activity:activity:1.6.0-alpha05"
```

Migracja aplikacji AndroidX zawierającej nieobsługiwane interfejsy API nawigacji wstecz do interfejsów API AndroidX

Jeśli Twoja aplikacja korzysta z bibliotek AndroidX, ale implementuje lub odwołuje się do nieobsługiwanych interfejsów API nawigacji wstecz, musisz przejść na korzystanie z interfejsów API AndroidX, aby obsługiwać nowe działanie.

Aby przenieść nieobsługiwane interfejsy API do interfejsów API AndroidX:

  1. Przejdź na system AndroidX OnBackPressedDispatcher z implementacją OnBackPressedCallback. Szczegółowe wskazówki znajdziesz w artykule Dodawanie niestandardowej opcji Wstecz.

  2. Gdy chcesz przestać przechwytywać gest Wstecz, wyłącz OnBackPressedCallback.

  3. Przestań przechwytywać zdarzenia „back” za pomocą funkcji OnBackPressed lub KeyEvent.KEYCODE_BACK.

  4. Zaktualizuj do AndroidX Activity 1.6.0-alpha05.

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    

Migracja aplikacji, która korzysta z nieobsługiwanych interfejsów API nawigacji wstecz, do interfejsów API platformy

Jeśli Twoja aplikacja nie może używać bibliotek AndroidX, a zamiast tego implementuje lub odwołuje się do niestandardowej nawigacji wstecz za pomocą nieobsługiwanych interfejsów API, musisz przejść na interfejs API platformy OnBackInvokedCallback.

Aby przenieść nieobsługiwane interfejsy API do interfejsu API platformy, wykonaj te czynności:

  1. Używaj nowego interfejsu API OnBackInvokedCallback na urządzeniach z Androidem 13 lub nowszym, a na urządzeniach z Androidem 12 lub starszym korzystaj z nieobsługiwanych interfejsów API.

  2. Zarejestruj niestandardową logikę w funkcji OnBackInvokedCallback za pomocą funkcji onBackInvokedDispatcher. Dzięki temu bieżąca aktywność nie zostanie zakończona, a Twoje wywołanie zwrotne będzie mogło zareagować na działanie Wstecz, gdy użytkownik użyje tej opcji w systemie.

  3. Gdy chcesz przestać przechwytywać gest wstecz, zarejestruj ponownie OnBackInvokedCallback. W przeciwnym razie użytkownicy mogą zauważyć niepożądane działanie podczas korzystania z systemu Wstecz – np. „zawieszanie się” między widokami, co zmusza ich do przymusowego zamknięcia aplikacji.

    Oto przykład migracji logiki z poziomu onBackPressed:

    Kotlin

    @Override
    fun onCreate() {
        if (BuildCompat.isAtLeastT()) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(
                OnBackInvokedDispatcher.PRIORITY_DEFAULT
            ) {
                /**
                 * onBackPressed logic goes here. For instance:
                 * Prevents closing the app to go home screen when in the
                 * middle of entering data to a form
                 * or from accidentally leaving a fragment with a WebView in it
                 *
                 * Unregistering the callback to stop intercepting the back gesture:
                 * When the user transitions to the topmost screen (activity, fragment)
                 * in the BackStack, unregister the callback by using
                 * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
                 * (https://developer.android.com/reference/kotlin/android/window/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
                 */
            }
        }
    }

    Java

    @Override
    void onCreate() {
      if (BuildCompat.isAtLeastT()) {
        getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
            OnBackInvokedDispatcher.PRIORITY_DEFAULT,
            () -> {
              /**
               * onBackPressed logic goes here - For instance:
               * Prevents closing the app to go home screen when in the
               * middle of entering data to a form
               * or from accidentally leaving a fragment with a WebView in it
               *
               * Unregistering the callback to stop intercepting the back gesture:
               * When the user transitions to the topmost screen (activity, fragment)
               * in the BackStack, unregister the callback by using
               * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
               * (https://developer.android.com/reference/kotlin/android/view/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
               */
            }
        );
      }
    }
  4. Przestań przechwytywać zdarzenia wstecz za pomocą zdarzeń OnBackPressed lub KeyEvent.KEYCODE_BACK w Androidzie w wersji 13 lub nowszej.

Można zarejestrować OnBackInvokedCallback za pomocą PRIORITY_DEFAULT lub PRIORITY_OVERLAY, co nie jest możliwe w przypadku podobnego pakietu AndroidX OnBackPressedCallback. W niektórych przypadkach przydatne może być zarejestrowanie wywołania zwrotnego za pomocą funkcji PRIORITY_OVERLAY.

Ma to zastosowanie w przypadku migracji z onKeyPreIme() i wywołania zwrotnego, które musi obsługiwać gest wstecz zamiast otwartego IME. IMEs rejestruje wywołania zwrotne z PRIORITY_DEFAULT po otwarciu. Zarejestruj wywołanie zwrotne w PRIORITY_OVERLAY, aby mieć pewność, że OnBackInvokedDispatcher przekaże gest wstecz do wywołania zwrotnego, a nie do otwartego IME.

Rezygnacja z przewidywanego przejścia wstecz

Aby zrezygnować, w tagu AndroidManifest.xml w tagu ustaw flagę android:enableOnBackInvokedCallback na false.


...

Ustawienie tej opcji na „Fałsz” powoduje:

  • Wyłącza animację systemową przewidywanego gestu cofania.
  • Ignoruje OnBackInvokedCallback, ale wywołuje OnBackPressedCallback.

Rezygnowanie na poziomie aktywności

Od Androida 16 flaga android:enableOnBackInvokedCallback umożliwia wyłączenie animacji systemowych prognozujących na poziomie aktywności. Dzięki temu łatwiej jest przenieść duże aplikacje z wieloma działaniami do przewidujących gestów wstecz.

Poniższy kod pokazuje przykład enableOnBackInvokedCallback ustawionego na włączanie animacji powrotu do ekranu głównego z poziomu MainActivity:

 ...>
     . . .

        android:enableOnBackInvokedCallback="false">

                    android:name=".MainActivity"
            android:enableOnBackInvokedCallback="true"
            ...
        
                    android:name=".SecondActivity"
            android:enableOnBackInvokedCallback="false"
            ...
        
    

Podczas korzystania z flagi android:enableOnBackInvokedCallback należy wziąć pod uwagę te kwestie:

  • Ustawienie android:enableOnBackInvokedCallback=false wyłącza przewidywane animacje wsteczne na poziomie aktywności lub aplikacji (w zależności od tego, gdzie ustawisz tag), a także instruuje system, aby ignorował wywołania interfejsu API platformy OnBackInvokedCallback. Wywołania OnBackPressedCallback będą jednak nadal działać, ponieważ interfejs OnBackPressedCallback jest zgodny ze starszymi wersjami i wywołuje interfejs API onBackPressed, który nie jest obsługiwany w Androidzie 13 i starszych wersjach.
  • Ustawienie flagi enableOnBackInvokedCallback na poziomie aplikacji ustala wartość domyślną dla wszystkich aktywności w aplikacji. Możesz ją zastąpić dla danej aktywności, ustawiając flagę na poziomie aktywności, jak pokazano w poprzednim przykładzie kodu.

Sprawdzone metody dotyczące wywołania zwrotnego

Oto sprawdzone metody korzystania z obsługiwanych wywołań zwrotnych systemu: BackHandler (dla funkcji tworzenia wiadomości), OnBackPressedCallback lub OnBackInvokedCallback.

Określ stan interfejsu użytkownika, który włącza i wyłącza poszczególne wywołania zwrotne.

Stan interfejsu użytkownika to właściwość opisująca interfejs użytkownika. Zalecamy wykonanie tych ogólnych czynności.

  1. Określ stan interfejsu użytkownika, który włącza i wyłącza poszczególne połączenia zwrotne.

  2. Określ ten stan za pomocą obserwowalnego typu danych, takiego jak StateFlow lub Stan tworzenia, i włącz lub wyłącz wywołanie zależnie od stanu.

Jeśli Twoja aplikacja wcześniej powiązała logikę cofnięcia z oświadczeniami warunkowymi, może to oznaczać, że reagujesz na zdarzenie cofnięcia po tym, jak już ono nastąpiło. Unikaj tego w przypadku nowych wywołań zwrotnych. Jeśli to możliwe, przenieś funkcję z powrotem poza instrukcję warunkową, a zamiast tego powiązać ją z obserwowalnym typem uchwytu danych.

Używanie wywołań zwrotnych systemu w logice interfejsu użytkownika

Logika interfejsu określa sposób wyświetlania interfejsu. Używaj wywołań zwrotnych systemu do wykonywania logiki interfejsu, np. wyświetlania wyskakującego okienka lub animacji.

Jeśli Twoja aplikacja umożliwia wywołanie systemu wstecz, animacje przewidujące nie są uruchamiane i musisz obsłużyć zdarzenie wstecz. Nie twórz wywołań zwrotnych tylko po to, aby wykonać logikę bez interfejsu użytkownika.

Jeśli na przykład przechwytujesz tylko zdarzenia back, aby je rejestrować, zamiast tego zrób to w cyklu życia aktywności lub fragmentu.

  • W przypadku aktywności do aktywności lub fragmentu do aktywności odnotuj, czy isFinishingonDestroy jest true w cyklu życia aktywności.
  • W przypadku fragmentów względem siebie rejestruj, czy isRemovingonDestroy jest prawdziwe w cyklu życia widoku fragmentu. Możesz też zalogować się za pomocą metod onBackStackChangeStarted lub onBackStackChangeCommitted w FragmentManager.OnBackStackChangedListener.

W przypadku Compose loguj w wywołaniu zwrotnym onCleared() funkcji ViewModel powiązanej z miejscem docelowym Compose. To najlepszy sygnał o tym, kiedy miejsce docelowe w komponowaniu jest usuwane ze stosu i niszczone.

Tworzenie wywołań obsługi błędów o jednym zadaniu

Do rozsyłacza możesz dodać wiele wywołań zwrotnych. Wywołania zwrotne są dodawane do stosu, w którym ostatnio dodane włączone wywołanie zwrotne obsługuje następny gest wstecz. Każdy gest wstecz jest obsługiwany przez jedno wywołanie zwrotne.

Łatwiej jest zarządzać stanem włączenia wywołania zwrotnego, jeśli ma ono tylko jedną odpowiedzialność. Na przykład:

kolejność wywołań zwrotnych w stosie.
Rysunek 2. Diagram stosu wywołania zwrotnego.

Na rysunku 2 widać, jak można umieścić w grupie wiele wywołań zwrotnych, z których każde odpowiada za inną czynność. Funkcja wywołania zwrotnego jest wykonywana tylko wtedy, gdy funkcje wywołania zwrotnego znajdujące się nad nią w zbiorze są wyłączone. W tym przykładzie wywołanie „Czy na pewno…” jest włączone, gdy użytkownik wpisuje dane w formularzu, i wyłączone w innych przypadkach. Gdy użytkownik przesunie palcem w bok, aby zamknąć formularz, wywołanie zwrotne otworzy okno potwierdzenia.

Inny wywoływany element może zawierać komponent Material, który obsługuje przewidywanie powrotów, przejście AndroidX za pomocą interfejsów API Progress lub inne niestandardowe wywołanie.

childFragmentManager wywoływana jest, jeśli powyższe wywołania są wyłączone, a stół zagnieżdżony tego FragmentManager nie jest pusty. childFragmentManager jest dołączony do Fragmentu. W tym przykładzie wywołanie zwrotne wewnętrzne jest wyłączone.

Podobnie wywołanie wewnętrzne supportFragmentManager jest wykonywane, jeśli powyższe wywołania są wyłączone, a stos nie jest pusty. To zachowanie jest spójne, gdy nawigacja odbywa się za pomocą elementów FragmentManager lub NavigationComponent, ponieważ NavigationComponent korzysta z elementu FragmentManager. W tym przykładzie ta funkcja wywołania zwrotnego jest wykonywana, jeśli użytkownik nie wpisał tekstu w formularzu, co spowodowało wyłączenie funkcji wywołania zwrotnego „Czy na pewno…?”.

Na koniec super.onBackPressed()to wywołanie na poziomie systemu, które jest wykonywane, jeśli powyższe wywołania są wyłączone. Aby wywołać animacje systemowe, takie jak animacja powrotu do domu, animacja między aktywnościami i animacja między zadaniami, stos wywołań supportFragmentManager musi być pusty, aby jego wewnętrzne wywołanie zwrotne było wyłączone.

Testowanie animacji przewidywanego przejścia wstecz

Jeśli nadal używasz Androida 13 lub Androida 14, możesz przetestować animację powrotu do ekranu głównego, którą przedstawia rysunek 1.

Aby przetestować tę animację, wykonaj te czynności:

  1. Na urządzeniu otwórz kolejno Ustawienia > System > Opcje programisty.

  2. Wybierz Animacje przewidywanego przejścia wstecz.

  3. Uruchom zaktualizowaną aplikację i użyj gestu cofania, aby zobaczyć, jak działa.