Udostępniaj niestandardową nawigację wstecz

Użytkownicy mogą cofać się między ekranami za pomocą przechodzenia wstecz. Większość urządzeń z Androidem ma przycisk Wstecz (fizyczny, programowy lub oparty na gestach). Zwykle nie trzeba dodawać przycisku Wstecz do aplikacji. Jednak urządzenia z systemem operacyjnym Android Automotive (AAOS) w trybie zgodności używają systemowego przycisku Wstecz. Obsługuje on nawigację, więc nie musisz dodawać własnego przycisku. Więcej informacji znajdziesz w sekcji Tryb zgodności AAOS.

Android utrzymuje stos wsteczny miejsc docelowych, gdy użytkownik porusza się po aplikacji. Zwykle umożliwia to Androidowi prawidłowe przejście do poprzednich miejsc docelowych po naciśnięciu przycisku Wstecz. W niektórych przypadkach aplikacja może jednak wymagać zaimplementowania własnego zachowania przycisku Wstecz, aby zapewnić jak najlepsze wrażenia użytkownika. Na przykład podczas korzystania z WebView możesz chcieć zastąpić domyślne zachowanie przycisku Wstecz, aby umożliwić użytkownikowi powrót do historii przeglądania internetu zamiast do poprzednich ekranów w aplikacji.

Implementowanie niestandardowego przechodzenia wstecz w Compose

W Jetpack Compose możesz obsługiwać niestandardowe przechodzenie wstecz za pomocą funkcji kompozycyjnej BackHandler.

Gdy używasz Navigation Compose, zwykle używasz NavController.navigateUp() lub NavController.popBackStack() aby przejść do poprzedniego ekranu w stosie wstecznym. Jednak BackHandler jest przydatny w przypadkach, gdy chcesz zaimplementować niestandardowe zachowanie, gdy użytkownik naciśnie systemowy przycisk Wstecz lub użyje gestu wstecz. Jeśli na przykład wyświetlasz w aplikacji WebView, możesz chcieć umożliwić użytkownikom powrót do historii przeglądania po naciśnięciu systemowego przycisku Wstecz.

Podstawowe użycie

Oto przykład pokazujący, jak przechwycić zdarzenie wstecz, aby kontrolować stan niestandardowy (np. zwijanie panelu):

@Composable
fun MyScreen() {
    var isExpanded by remember { mutableStateOf(false) }

    // Intercept the back button or gesture only when isExpanded is true
    BackHandler(enabled = isExpanded) {
        // Collapsing the content disables this handler, so it does not
        // receive the next back event.
        isExpanded = false
    }

    if (isExpanded) {
        Text("Expanded content. Go back to collapse it.")
    } else {
        Button(onClick = { isExpanded = true }) {
            Text("Expand")
        }
    }
}

Przechwytywanie w drzewie elementów kompozycyjnych

Jeśli masz kilka włączonych elementów kompozycyjnych BackHandler na różnych poziomach drzewa elementów kompozycyjnych, tylko najbardziej wewnętrzny z nich przechwytuje zdarzenie wstecz.

Implementowanie niestandardowego przechodzenia wstecz za pomocą widoków

ComponentActivity, klasa bazowa dla FragmentActivity i AppCompatActivity, umożliwia kontrolowanie zachowania przycisku Wstecz za pomocą OnBackPressedDispatcher, który można pobrać, wywołując getOnBackPressedDispatcher().

OnBackPressedDispatcher określa, jak zdarzenia przycisku Wstecz są wysyłane do co najmniej 1 obiektu OnBackPressedCallback. Konstruktor OnBackPressedCallback przyjmuje wartość logiczną dla początkowego stanu włączenia. Tylko wtedy, gdy wywołanie zwrotne jest włączone, np. gdy isEnabled() zwraca wartość true, dyspozytor wywoła handleOnBackPressed() wywołania zwrotnego, aby obsłużyć zdarzenie przycisku Wstecz. Stan włączenia możesz zmienić, wywołując setEnabled().

Wywołania zwrotne są dodawane za pomocą metod addCallback. Użyj metody addCallback(), która przyjmuje LifecycleOwner. W ten sposób OnBackPressedCallback jest dodawany tylko wtedy, gdy LifecycleOwner ma Lifecycle.State.STARTED. Aktywność usuwa też zarejestrowane wywołania zwrotne, gdy powiązany z nimi LifecycleOwner zostanie zniszczony, co zapobiega wyciekom pamięci i umożliwia używanie ich we fragmentach lub innych właścicielach cyklu życia, których czas życia jest krótszy niż czas życia aktywności.

Oto przykład implementacji wywołania zwrotnego:

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }
    ...
}

Możesz podać kilka wywołań zwrotnych za pomocą addCallback(). W takim przypadku wywołania zwrotne są wywoływane w odwrotnej kolejności, w jakiej zostały dodane – wywołanie zwrotne dodane jako ostatnie jest pierwsze, które ma szansę obsłużyć zdarzenie przycisku Wstecz. Jeśli na przykład dodasz 3 wywołania zwrotne o nazwach one, two i three w tej kolejności, zostaną one wywołane w kolejności three, two i one.

Wywołania zwrotne są zgodne ze wzorcem łańcucha odpowiedzialności. Każde wywołanie zwrotne w łańcuchu jest wywoływane tylko wtedy, gdy poprzednie wywołanie zwrotne nie było włączone. Oznacza to, że w poprzednim przykładzie wywołanie zwrotne two zostanie wywołane tylko wtedy, gdy wywołanie zwrotne three nie było włączone. Wywołanie zwrotne one zostanie wywołane tylko wtedy, gdy wywołanie zwrotne two nie było włączone, i ten wzorzec będzie się powtarzać w przypadku wszystkich dodatkowych wywołań zwrotnych.

Pamiętaj, że gdy wywołanie zwrotne zostanie dodane za pomocą addCallback(), nie zostanie dodane do łańcucha odpowiedzialności, dopóki LifecycleOwner nie przejdzie do stanu Lifecycle.State.STARTED.

W przypadku zmian tymczasowych zdecydowanie zalecamy zmianę stanu włączenia wywołania zwrotnego, ponieważ zachowuje to opisaną wcześniej kolejność, co jest szczególnie ważne, jeśli masz wywołania zwrotne zarejestrowane u kilku różnych zagnieżdżonych właścicieli cyklu życia.

Jeśli chcesz całkowicie usunąć wywołanie zwrotne, wywołaj remove(). Zwykle nie jest to konieczne, ponieważ wywołania zwrotne są automatycznie usuwane, gdy powiązany z nimi LifecycleOwner zostanie zniszczony.