Добавить поддержку интеллектуального жеста назад.

Рисунок 1. Макет предиктивного жеста «Назад» на телефоне

Функция навигации жестами Predictive Back позволяет пользователям предварительно просматривать, куда они будут перенаправлены свайпом назад.

Например, с помощью жеста «назад» можно отобразить анимированный предварительный просмотр главного экрана позади вашего приложения, как показано на макете на рисунке 1.

Начиная с Android 15, опция для разработчиков, позволяющая использовать предиктивную анимацию «Назад», больше недоступна. Системные анимации, такие как «Возврат на главный экран», «Перекрестная задача» и «Перекрестная активность», теперь отображаются для приложений, которые включили предиктивную анимацию «Назад» полностью или на уровне отдельных действий.

Вы можете протестировать эту анимацию возврата домой (как описано в следующем разделе этой страницы).

Для поддержки предиктивного жеста «Назад» необходимо обновить приложение, используя обратно совместимое API OnBackPressedCallback AppCompat версии 1.6.0-alpha05 (AndroidX) или выше, либо новый API платформы OnBackInvokedCallback . Большинство приложений используют обратно совместимое API AndroidX.

Это обновление предоставляет путь миграции для правильного перехвата обратной навигации, который включает замену обратных перехватов из KeyEvent.KEYCODE_BACK и любых классов с методами onBackPressed , такими как Activity и Dialog , на новые системные API Back.

Видео Codelab и Google I/O

Помимо документации на этой странице, ознакомьтесь с нашей лабораторной работой . Она представляет собой типичный пример реализации WebView, обрабатывающего предиктивный жест «Назад» с помощью API AndroidX Activity.

Вы также можете посмотреть наше видео с конференции Google I/O, в котором рассматриваются дополнительные примеры реализации API AndroidX и платформы.

Обновите приложение, которое использует обратную навигацию по умолчанию.

Функция предиктивного возврата включена по умолчанию.

Если ваше приложение использует фрагменты или компонент навигации, также обновите его до AndroidX Activity 1.6.0-alpha05 или выше.

Обновите приложение, которое использует пользовательскую обратную навигацию

Если ваше приложение реализует пользовательское поведение возврата, существуют различные пути миграции в зависимости от того, использует ли оно AndroidX и как оно обрабатывает возврат возврата.

Ваше приложение использует AndroidX Как ваше приложение обрабатывает обратную навигацию Рекомендуемый путь миграции (ссылка на этой странице)
Да API AndroidX Перенести существующую реализацию AndroidX обратно
Неподдерживаемые API платформы Перенести приложение AndroidX, содержащее неподдерживаемые API обратной навигации, на API AndroidX
Нет Неподдерживаемые API платформы, возможность миграции Перенесите приложение, использующее неподдерживаемые API обратной навигации, на API платформы
Неподдерживаемые API платформы, но невозможность миграции Временно откажитесь, установив атрибут android:enableOnBackInvokedCallback на false в теге <application> или <activity> файла AndroidManifest.xml вашего приложения.

Перенос реализации обратной навигации AndroidX

Этот вариант использования является наиболее распространённым (и наиболее рекомендуемым). Он применим к новым или существующим приложениям, реализующим пользовательскую обработку навигации жестами с помощью OnBackPressedDispatcher , как описано в разделе «Реализация пользовательской навигации «Назад»» .

Чтобы убедиться, что API, которые уже используют OnBackPressedDispatcher (например, Fragments и Navigation Component), без проблем работают с предиктивным жестом «назад», выполните обновление до 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"
```

Перенести приложение AndroidX, содержащее неподдерживаемые API обратной навигации, на API AndroidX

Если ваше приложение использует библиотеки AndroidX, но реализует или ссылается на неподдерживаемые API обратной навигации, вам необходимо перейти на использование API AndroidX для поддержки нового поведения.

Чтобы перенести неподдерживаемые API в API AndroidX:

  1. Перенесите логику обработки обратных вызовов вашей системы в OnBackPressedDispatcher AndroidX с реализацией OnBackPressedCallback . Подробные инструкции см. в разделе Предоставление пользовательской обратной навигации .

  2. Отключите OnBackPressedCallback , когда будете готовы прекратить перехват жеста «назад».

  3. Прекратить перехват обратных событий через OnBackPressed или KeyEvent.KEYCODE_BACK .

  4. Обязательно обновитесь до 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"
    

Перенесите приложение, использующее неподдерживаемые API обратной навигации, на API платформы

Если ваше приложение не может использовать библиотеки AndroidX и вместо этого реализует или ссылается на пользовательскую навигацию «Назад» с использованием неподдерживаемых API, вам необходимо перейти на API платформы OnBackInvokedCallback .

Выполните следующие шаги для переноса неподдерживаемых API в API платформы:

  1. Используйте новый API OnBackInvokedCallback на устройствах под управлением Android 13 или выше и полагайтесь на неподдерживаемые API на устройствах под управлением Android 12 или ниже.

  2. Зарегистрируйте свою собственную логику обратного вызова в OnBackInvokedCallback с помощью onBackInvokedDispatcher . Это предотвращает завершение текущего действия, и ваш обратный вызов получает возможность отреагировать на действие «Назад» после того, как пользователь завершит навигацию «Назад» в системе.

  3. Отмените регистрацию OnBackInvokedCallback , когда будете готовы прекратить перехват жеста «Назад». В противном случае пользователи могут столкнуться с нежелательным поведением при использовании системной навигации «Назад», например, с «зависанием» между представлениями и вынужденным выходом из приложения.

    Вот пример того, как перенести логику из onBackPressed :

    Котлин

    @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)
                 */
            }
        }
    }

    Ява

    @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. Прекратите перехват обратных событий с помощью OnBackPressed или KeyEvent.KEYCODE_BACK для Android 13 и более поздних версий.

Вы можете зарегистрировать OnBackInvokedCallback с PRIORITY_DEFAULT или PRIORITY_OVERLAY , чего нет в аналогичном OnBackPressedCallback в AndroidX. Регистрация обратного вызова с PRIORITY_OVERLAY полезна в некоторых случаях.

Это применимо при миграции с onKeyPreIme() , когда ваш обратный вызов должен получать жест «Назад» вместо открытого IME. IME регистрируют обратные вызовы с PRIORITY_DEFAULT при открытии. Зарегистрируйте свой обратный вызов с PRIORITY_OVERLAY , чтобы OnBackInvokedDispatcher отправлял жест «Назад» обратному вызову, а не открытому IME.

Отказаться от предиктивного возврата

Чтобы отказаться, в AndroidManifest.xml в теге <application> установите для флага android:enableOnBackInvokedCallback значение false .

<application
    ...
    android:enableOnBackInvokedCallback="false"
    ... >
...
</application>

Установка значения false приводит к следующему:

  • Отключает анимацию предиктивной системы жестов «Назад».
  • Игнорирует OnBackInvokedCallback , но вызовы OnBackPressedCallback продолжают работать.

Отказаться на уровне активности

Начиная с Android 16, флаг android:enableOnBackInvokedCallback позволяет отключить предиктивную системную анимацию на уровне активности. Это упрощает миграцию крупных многофункциональных приложений на предиктивные жесты «Назад».

В следующем коде показан пример enableOnBackInvokedCallback , установленного для включения анимации возврата домой из MainActivity :

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

        <activity
            android:name=".MainActivity"
            android:enableOnBackInvokedCallback="true"
            ...
        </activity>
        <activity
            android:name=".SecondActivity"
            android:enableOnBackInvokedCallback="false"
            ...
        </activity>
    </application>
</manifest>

При использовании флага android:enableOnBackInvokedCallback следует учитывать следующие моменты:

  • Установка android:enableOnBackInvokedCallback=false отключает предиктивную обратную анимацию либо на уровне активности, либо на уровне приложения, в зависимости от того, где установлен тег, и указывает системе игнорировать вызовы API платформы OnBackInvokedCallback . Однако вызовы OnBackPressedCallback продолжают выполняться, поскольку OnBackPressedCallback обратно совместим и вызывает API onBackPressed , который не поддерживается до Android 13.
  • Установка флага enableOnBackInvokedCallback на уровне приложения устанавливает значение по умолчанию для всех действий в приложении. Вы можете переопределить значение по умолчанию для каждого действия, установив флаг на уровне действия, как показано в предыдущем примере кода.

Лучшие практики обратного вызова

Ниже приведены рекомендации по использованию поддерживаемых системных обратных вызовов: BackHandler (для Compose), OnBackPressedCallback или OnBackInvokedCallback .

Определите состояние пользовательского интерфейса, которое включает и выключает каждый обратный вызов.

Состояние пользовательского интерфейса — это свойство, описывающее пользовательский интерфейс. Мы рекомендуем выполнить следующие шаги общего уровня.

  1. Определите состояние пользовательского интерфейса, которое включает и выключает каждый обратный вызов.

  2. Определите это состояние, используя наблюдаемый тип держателя данных , например StateFlow или Compose State, и включите или отключите обратный вызов при изменении состояния.

Если ваше приложение ранее связывало обратную логику с условными операторами, это может означать, что вы реагируете на событие обратного вызова после того, как оно уже произошло. Избегайте этого шаблона с новыми обратными вызовами. По возможности вынесите обратный вызов за пределы условного оператора и вместо этого свяжите его с наблюдаемым типом хранилища данных.

Используйте системные обратные вызовы для логики пользовательского интерфейса

Логика пользовательского интерфейса определяет, как его отображать. Используйте системные обратные вызовы для запуска логики пользовательского интерфейса, например, отображения диалогового окна или анимации.

Если ваше приложение включает OnBackPressedCallback или OnBackInvokedCallback с PRIORITY_DEFAULT или PRIORITY_OVERLAY , предиктивные обратные анимации не запускаются, и вам необходимо обработать событие возврата. Не создавайте эти обратные вызовы для выполнения бизнес-логики или ведения журнала.

Используйте следующие подходы, если ваше приложение должно выполнять бизнес-логику или регистрировать журнал, когда пользователь выполняет свайп назад:

  • Используйте OnBackInvokedCallback с PRIORITY_SYSTEM_NAVIGATION_OBSERVER на устройствах под управлением Android 16 и выше. Это создаст обратный вызов наблюдателя, который не использует событие возврата. Например, вы можете зарегистрировать этот обратный вызов, когда пользователь смахивает экран назад из корневой активности или, другими словами, когда пользователь покидает приложение. В этом случае вы можете зарегистрировать событие возврата или запустить другую бизнес-логику, и анимация возврата на главную страницу будет по-прежнему воспроизводиться.
  • Для случаев «активность-активность» или «фрагмент-активность» регистрируйте, если isFinishing в пределах onDestroy имеет true в пределах жизненного цикла Activity.
  • В случаях «фрагмент-фрагмент» регистрируйте, если isRemoving в onDestroy имеет значение true в течение жизненного цикла представления фрагмента. Или регистрируйте с помощью методов onBackStackChangeStarted или onBackStackChangeCommitted в FragmentManager.OnBackStackChangedListener .
  • В случае Compose регистрируйте данные в обратном вызове onCleared() ViewModel , связанном с назначением Compose. Это лучший сигнал для определения момента, когда назначение Compose извлекается из стека возвратов и уничтожается.

Создание обратных вызовов с единой ответственностью

Вы можете добавить несколько обратных вызовов в диспетчер. Они добавляются в стек, в котором последний добавленный активный обратный вызов обрабатывает следующий жест «Назад» с одним обратным вызовом на каждый жест «Назад».

Управлять состоянием обратного вызова проще, если у него есть одна обязанность. Например:

Упорядочивание обратных вызовов в стеке.
Рисунок 2. Диаграмма стека обратных вызовов.

На рисунке 2 показано, как можно разместить несколько обратных вызовов в стеке, каждый из которых отвечает за одну функцию. Обратный вызов выполняется только в том случае, если отключены все обратные вызовы, расположенные выше в стеке. В этом примере обратный вызов «Вы уверены...» включается, когда пользователь вводит данные в форму, и отключается в противном случае. Обратный вызов открывает диалоговое окно подтверждения, когда пользователь смахивает экран назад для выхода из формы.

Другой обратный вызов может включать материальный компонент, поддерживающий предиктивный обратный вызов, переход AndroidX с использованием API Progress или другой пользовательский обратный вызов.

Обратный вызов childFragmentManager выполняется, если указанные выше обратные вызовы отключены, а стек возвратов для этого FragmentManager не пуст, при этом childFragmentManager присоединён к фрагменту. В данном примере этот внутренний обратный вызов отключен.

Аналогично, внутренний обратный вызов supportFragmentManager срабатывает, если указанные выше обратные вызовы отключены, а его стек непустой. Это поведение одинаково при использовании FragmentManager или NavigationComponent для навигации, поскольку NavigationComponent использует FragmentManager . В данном примере этот обратный вызов срабатывает, если пользователь не ввёл текст в форму, что приводит к отключению обратного вызова «Вы уверены...».

Наконец, super.onBackPressed() — это системный обратный вызов, который также срабатывает, если указанные выше обратные вызовы отключены. Для запуска системных анимаций, таких как возврат на главную страницу, кросс-активность и кросс-задача, стек возвратов supportFragmentManager должен быть пуст, поэтому его внутренний обратный вызов отключен.

Протестируйте анимацию предиктивного жеста «Назад»

Если вы все еще используете Android 13 или Android 14, вы можете протестировать анимацию возврата на главный экран, показанную на рисунке 1.

Чтобы протестировать эту анимацию, выполните следующие шаги:

  1. На вашем устройстве перейдите в раздел Настройки > Система > Параметры разработчика .

  2. Выберите Предиктивная анимация возврата .

  3. Запустите обновленное приложение и используйте жест «назад», чтобы увидеть его в действии.