Dodawanie obsługi animacji przewidywanego przejścia wstecz w widokach

Za pomocą widoków lub biblioteki Jetpack Compose możesz tworzyć niestandardowe animacje i przejścia w aplikacji, niestandardowe animacje między aktywnościami i fragmentami oraz niestandardowe gesty powrotu z przewidywaniem. Aby wypróbować metodę Compose, przeczytaj artykuł Dodawanie obsługi animacji przewidywanego przejścia wstecz.

Dodawanie niestandardowych przejść za pomocą interfejsu Progress API

W przypadku Androida X Activity w wersji 1.8.0-alpha01 lub nowszej możesz używać interfejsów Predictive Back Progress API do tworzenia niestandardowych animacji gestu przewidywanego przejścia wstecz w aplikacji. Interfejsy Progress API są przydatne do animowania widoków, ale mają ograniczenia w przypadku animowania przejść między fragmentami. W OnBackPressedCallback wprowadziliśmy metody handleOnBackProgressed, handleOnBackCancelledhandleOnBackStarted, które umożliwiają animowanie obiektów podczas przesuwania palcem w tył. Użyj tych metod, jeśli chcesz dostosować więcej animacji niż domyślne animacje systemowe lub animacje komponentów Material.

Spodziewamy się, że większość aplikacji będzie korzystać ze zgodnych wstecznie interfejsów API AndroidX, ale w Androidzie 14 i nowszych wersjach dostępne są też podobne interfejsy API platformy w ramach interfejsu OnBackAnimationCallback, które można testować.

Używanie interfejsów API postępu z przejściami AndroidX

Interfejsów API postępu można używać z AndroidX Transitions 1.5.0-alpha01 lub nowszym na Androidzie 14 i nowszym do tworzenia przejść w ramach funkcji przewidywania powrotu.

  1. Użyj TransitionManager#controlDelayedTransition zamiast beginDelayedTransition, aby odtwarzać przejścia, gdy użytkownik przesuwa palcem do tyłu.
  2. Utwórz przejście w usłudze handleOnBackStarted.
  3. Odtwórz przejście ze zdarzeniem wstecz w ramach handleOnBackProgressed, powiązując currentFractionBackEvent.progress, co pokazuje, jak daleko użytkownik przesunął palcem w tył.
  4. Zakończ przejście po wykonaniu przez użytkownika gestu cofnięcia w handleOnBackPressed.
  5. Na koniec zresetuj stan przejścia w handleOnBackCancelled.

Poniższy film, kod Kotlin i XML pokazują niestandardowe przejście między 2 polami zaimplementowane za pomocą OnBackPressedCallback:

    class MyFragment : Fragment() {

    val transitionSet = TransitionSet().apply {
        addTransition(Fade(Fade.MODE_OUT))
        addTransition(ChangeBounds())
        addTransition(Fade(Fade.MODE_IN))
    }
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val callback = object : OnBackPressedCallback(enabled = false) {

            var controller: TransitionSeekController? = null

            @RequiresApi(34)
            override fun handleOnBackStarted(backEvent: BackEvent) {
                // Create the transition
                controller = TransitionManager.controlDelayedTransition(
                    binding.card,
                    transitionSet
                )
                changeTextVisibility(ShowText.SHORT)
            }

            @RequiresApi(34)
            override fun handleOnBackProgressed(backEvent: BackEvent) {
                // Play the transition as the user swipes back
                if (controller?.isReady == true) {
                    controller?.currentFraction = backEvent.progress
                }
            }

            override fun handleOnBackPressed() {
                // Finish playing the transition when the user commits back
                controller?.animateToEnd()
                this.isEnabled = false
            }

            @RequiresApi(34)
            override fun handleOnBackCancelled() {
                // If the user cancels the back gesture, reset the state
                transition(ShowText.LONG)
            }
        }

        binding.shortText.setOnClickListener {
            transition(ShowText.LONG)
            callback.isEnabled = true
        }

        this.requireActivity().onBackPressedDispatcher.addCallback(callback)
    }

    private fun transition(showText: ShowText) {
        TransitionManager.beginDelayedTransition(
            binding.card,
            transitionSet
        )
        changeTextVisibility(showText)
    }

    enum class ShowText { SHORT, LONG }
    private fun changeTextVisibility(showText: ShowText) {
        when (showText) {
            ShowText.SHORT -> {
                binding.shortText.isVisible = true
                binding.longText.isVisible = false
            }
            ShowText.LONG -> {
                binding.shortText.isVisible = false
                binding.longText.isVisible = true
            }
        }
    }
}
  
<?xml version="1.0" encoding="utf-8"?>
...
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        ...>

        <TextView
            android:id="@+id/short_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ... />

        <TextView
            android:id="@+id/long_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            .../>

    </androidx.constraintlayout.widget.ConstraintLayout>

Podczas pracy z przejściami do poprzedniej strony pamiętaj o tych kwestiach:

  • Użyj isSeekingSupported, aby sprawdzić, czy przejście obsługuje predykcyjne cofanie.
  • Zastąp isSeekingSupported, aby zwracać wartość „prawda” w przypadku przejść niestandardowych.
  • Utwórz po 1 kontrolerze na każdą animację.
  • Przejścia do poprzedniej strony są obsługiwane w przypadku przejść AndroidX, ale nie w przypadku przejść frameworka. Zrezygnuj z przejść frameworka i zamiast nich używaj przejść Animator i AndroidX.
  • Przejścia z użyciem funkcji przewidywanego powrotu są obsługiwane na urządzeniach z Androidem 14 i nowszym i nie są wstecznie kompatybilne.
  • Obsługiwane są też przejścia utworzone za pomocą scen XML. W handleOnBackStarted ustaw TransitionSeekController na wynik TransitionManager.createSeekController zamiast na wynik controlDelayedTransition.

Dodatkowe materiały