Добавьте поддержку анимаций с предпросмотром для жеста "Назад" в представлениях

Вы можете создавать собственные анимации и переходы свойств в приложении, собственные анимации между действиями и собственные анимации между фрагментами с помощью жестов прогнозирования назад, используя представления или Compose. Чтобы попробовать способ с Compose, прочитайте статью Как добавить поддержку анимаций с предпросмотром для жеста "Назад".

Как добавить собственные переходы с помощью Progress API

В AndroidX Activity 1.8.0-alpha01 и более поздних версиях можно использовать Predictive Back Progress API, чтобы создавать собственные анимации для предпросмотра для жеста "Назад" в приложении. Progress API полезны для анимации представлений, но имеют ограничения при анимации переходов между фрагментами. В OnBackPressedCallback мы добавили методы handleOnBackProgressed, handleOnBackCancelled и handleOnBackStarted, чтобы анимировать объекты, когда пользователь проводит по экрану назад. Используйте эти методы, если вам нужно настроить больше, чем стандартные анимации, предоставляемые системой, или анимации компонентов Material.

Мы ожидаем, что большинство приложений будут использовать обратно совместимые API AndroidX, но в интерфейсе OnBackAnimationCallback также есть похожие API платформы, доступные для тестирования в Android 14 и более поздних версиях.

Как использовать Progress API с переходами AndroidX

API Progress можно использовать с AndroidX Transitions 1.5.0-alpha01 или более поздней версии на Android 14 и более поздних версиях, чтобы создавать переходы с предпросмотром для жеста "Назад".

  1. Используйте TransitionManager#controlDelayedTransition вместо beginDelayedTransition, чтобы воспроизводить переходы, когда пользователь проводит по экрану назад.
  2. Создайте переход в handleOnBackStarted.
  3. Воспроизведите переход с событием возврата в handleOnBackProgressed, связав currentFraction с BackEvent.progress, чтобы показать, насколько далеко пользователь провел пальцем назад.
  4. Завершите переход после того, как пользователь выполнит жест "Назад" в handleOnBackPressed.
  5. Наконец, сбросьте состояние перехода в handleOnBackCancelled.

В видео, коде Kotlin и XML ниже показан пример перехода между двумя блоками, реализованного с помощью 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>

При работе с переходами с предпросмотром для жеста "Назад" учитывайте следующее:

  • Используйте isSeekingSupported, чтобы проверить, поддерживает ли переход предпросмотр для жеста "Назад".
  • Переопределите isSeekingSupported, чтобы возвращать значение true для персонализированных переходов.
  • Создайте по одному контроллеру для каждой анимации.
  • Переходы с предпросмотром для жеста "Назад" поддерживаются в AndroidX, но не в фреймворке. Перейдите с переходов фреймворка на переходы Animator и AndroidX.
  • Переходы с предпросмотром для жеста "Назад" поддерживаются на устройствах с Android 14 и более поздними версиями и несовместимы с предыдущими версиями.
  • Также поддерживаются переходы, созданные с помощью XML-сцен. В handleOnBackStarted задайте для TransitionSeekController результат TransitionManager.createSeekController вместо результата controlDelayedTransition.

Дополнительные ресурсы