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

Za pomocą widoków lub biblioteki 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ć sposób Compose, zapoznaj się z artykułem 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 celu powrotu. 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 AndroidX API, ale w Androidzie 14 i nowszych wersjach dostępne są też podobne interfejsy platformy w ramach interfejsu OnBackAnimationCallback, które można testować.

Korzystanie z interfejsów Progress API z przejściami AndroidX

Interfejsów API postępu można używać z Androidem 14 lub nowszym oraz biblioteką AndroidX Transitions w wersji 1.5.0-alpha01 lub nowszej, aby tworzyć przejścia 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 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 do tyłu.
  4. Zakończ przejście po wykonaniu przez użytkownika gestu cofania w handleOnBackPressed.
  5. Na koniec zresetuj stan przejścia w handleOnBackCancelled.

Poniższy film, kod Kotlin i kod XML przedstawiają niestandardowe przejście między 2 polami zaimplementowane za pomocą funkcji 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ę.
  • Przewidywane przejścia wstecz 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 przewidywaniem 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