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

Рисунок 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

В дополнение к использованию этой документации на этой странице, попробуйте нашу codelab . Она обеспечивает общую реализацию варианта использования 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. Перенесите логику обработки Back вашей системы в 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 . Это предотвращает завершение текущей активности, и ваш обратный вызов получает возможность отреагировать на действие Back, как только пользователь завершит системную навигацию Back.

  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 , что недоступно в похожем AndroidX OnBackPressedCallback . Регистрация обратного вызова с 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, и включите или отключите обратный вызов по мере изменения состояния.

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

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

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

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

Например, если вы перехватываете обратные события только для регистрации, регистрируйте их в жизненном цикле Activity или Fragment.

  • Для случаев «активность-активность» или «фрагмент-активность» регистрируйте, если isFinishing в onDestroy имеет true в жизненном цикле Activity.
  • Для случаев фрагмент-к-фрагменту регистрируйте, если isRemoving в onDestroy имеет значение true в жизненном цикле представления фрагмента. Или регистрируйте с помощью методов onBackStackChangeStarted или onBackStackChangeCommitted в FragmentManager.OnBackStackChangedListener .

Для случая Compose войдите в обратный вызов onCleared() ViewModel , связанный с назначением Compose. Это лучший сигнал для определения того, когда назначение Compose выталкивается из стека и уничтожается.

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

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

Легче управлять включенным состоянием обратного вызова, если этот обратный вызов имеет одну ответственность. Например:

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

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

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

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

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

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

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

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

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

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

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

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