Adicionar suporte para o gesto de volta preditivo

Figura 1. Mockup da aparência do gesto de volta preditivo em um smartphone

O Android 14 (nível 34 da API) adiciona suporte a outras animações do sistema e APIs para criar animações personalizadas. Para mais informações, consulte Adicionar suporte a animações de volta preditiva integradas e personalizadas.

O gesto "Voltar" pode, por exemplo, mostrar uma visualização animada da tela inicial atrás do app, como apresentado na Figura 1. No Android 13 e versões mais recentes, é possível testar essa animação de volta à tela inicial ativando uma opção para desenvolvedores, conforme descrito nesta página.

Para oferecer suporte ao gesto de volta preditivo, é necessário atualizar o app usando o OnBackPressedCallback da API compatível com versões anteriores AppCompat 1.6.0-alpha05 (AndroidX) ou uma versão mais recente, ou ainda usando a nova API da plataforma OnBackInvokedCallback. A maioria dos apps usa a API AndroidX compatível com versões anteriores.

Essa atualização oferece um caminho de migração para interceptar corretamente a navegação de retorno, o que envolve substituir essas interceptações em KeyEvent.KEYCODE_BACK e todas as classes com métodos onBackPressed, como Activity e Dialog, pelas novas APIs Back do sistema.

Codelab e vídeo do Google I/O

Além de usar a documentação disponível nesta página, acesse nosso codelab. Ele apresenta a implementação de um caso de uso comum de um WebView que processa o gesto de volta preditivo usando as APIs Activity do AndroidX.

Você também pode assistir ao vídeo do Google I/O, que mostra outros exemplos de implementação das APIs do AndroidX e da plataforma.

Atualizar um app que usa a navegação de retorno padrão

Se o app não implementa nenhum comportamento personalizado para a ação "Voltar", ou seja, se é o sistema que processa essa ação, a atualização para oferecer suporte ao novo recurso é um processo simples. Ative esse recurso conforme descrito neste guia.

Se o app usa fragmentos ou o componente Navigation, faça upgrade para o AndroidX Activity 1.6.0-alpha05 ou versões mais recentes.

Atualizar um app que usa uma navegação de retorno personalizada

Existem diferentes caminhos de migração para apps que implementam um comportamento personalizado para a ação "Voltar", dependendo se o app usa o AndroidX e da maneira como ele processa a navegação de retorno.

O app usa o AndroidX Como o app processa a navegação de retorno Caminho de migração recomendado (link nesta página)
Sim APIs do AndroidX Migrar uma implementação da ação "Voltar" existente do AndroidX
APIs de plataforma sem suporte Migrar para as APIs do AndroidX um aplicativo AndroidX com APIs de navegação de retorno sem suporte
Não App usa APIs de plataforma sem suporte, mas é possível migrá-lo Migrar para as APIs de plataforma um aplicativo que usa APIs de navegação de retorno sem suporte
App usa APIs de plataforma sem suporte, mas não é possível migrá-lo Adiar a ativação do recurso até que ele seja obrigatório

Migrar a implementação da navegação de retorno do AndroidX

Esse é o caso de uso mais comum e recomendado. Ele se aplica a apps novos ou antigos que processam uma navegação de retorno por gesto personalizada com OnBackPressedDispatcher, conforme descrito em Oferecer navegação de retorno personalizada.

Caso seu app se encaixe nessa categoria, siga estas etapas para adicionar o suporte para o gesto de volta preditivo:

  1. Para garantir que as APIs que já usam as APIs OnBackPressedDispatcher (como fragmentos e o componente Navigation) funcionem perfeitamente com o gesto de volta preditivo, faça upgrade para a 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"
    
  2. Ative o gesto de volta preditivo, conforme descrito nesta página.

Migrar para as APIs do AndroidX um aplicativo AndroidX com APIs de navegação de retorno sem suporte

Se o app usa as bibliotecas do AndroidX, mas implementa ou referencia APIs de navegação de retorno sem suporte, você precisa migrar para as APIs do AndroidX para conseguir oferecer suporte ao novo comportamento.

Para migrar de APIs sem suporte e passar a usar as APIs do AndroidX:

  1. Migre a lógica de processamento da ação "Voltar" do sistema para o OnBackPressedDispatcher do AndroidX, implementando OnBackPressedCallback. Encontre instruções detalhadas em Oferecer navegação de retorno personalizada.

  2. Desative o OnBackPressedCallback quando estiver tudo pronto para deixar de interceptar o gesto de volta.

  3. Pare de usar OnBackPressed ou KeyEvent.KEYCODE_BACK para interceptar eventos de retorno.

  4. Faça upgrade para o 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"
    
  5. Depois de migrar o app, ative o gesto de volta preditivo, conforme descrito nesta página, para conferir a animação do sistema para voltar à tela inicial.

Migrar para as APIs de plataforma um aplicativo que usa APIs de navegação de retorno sem suporte

Caso não seja possível usar as bibliotecas do AndroidX no app e ele implemente ou faça referência à navegação de retorno personalizada usando APIs sem suporte, você precisa migrar para a API de plataforma OnBackInvokedCallback.

Conclua as etapas a seguir para migrar das APIs sem suporte e passar a usar a API da plataforma:

  1. Use a nova API OnBackInvokedCallback em dispositivos com o Android 13 ou versões mais recentes. No Android 12 ou versões anteriores, você precisará usar APIs sem suporte.

  2. Registre sua lógica de retorno personalizada em OnBackInvokedCallback com o onBackInvokedDispatcher. Isso impede que a atividade em curso seja finalizada. Assim, o callback poderá reagir à ação "Voltar" quando o usuário concluir a navegação de retorno.

  3. Cancele o registro do OnBackInvokedCallback quando estiver tudo pronto para deixar de interceptar o gesto de volta. Caso contrário, o app pode apresentar comportamentos indesejáveis para a ação "Voltar". Por exemplo, ele pode ficar preso entre as duas visualizações, fazendo com que o usuário tenha que forçar o fechamento.

    Confira um exemplo de como migrar a lógica de onBackPressed:

    Kotlin

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

    Java

    @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. Pare de usar OnBackPressed ou KeyEvent.KEYCODE_BACK para interceptar eventos de retorno no Android 13 e versões mais recentes.

  5. Depois de migrar o app, ative o gesto de volta preditivo, conforme descrito nesta página, para que OnBackInvokedCallback entre em vigor.

Você pode registrar um OnBackInvokedCallback com PRIORITY_DEFAULT ou PRIORITY_OVERLAY, que não está disponível em um OnBackPressedCallback do AndroidX semelhante. Registrar um callback com PRIORITY_OVERLAY é útil em alguns casos. Um caso em que isso pode ser aplicado é quando você migra de onKeyPreIme() e seu callback precisar receber o gesto "Voltar" em vez de um IME aberto. Os IMEs registram callbacks com PRIORITY_DEFAULT quando abertos. Registre o callback com PRIORITY_OVERLAY para garantir que OnBackInvokedDispatcher envie o gesto de volta ao callback, em vez do IME aberto.

Ativar o gesto de volta preditivo

Depois de entender como atualizar o app de acordo com seu caso específico, ofereça suporte ao gesto de volta preditivo.

Para ativar esse recurso, em AndroidManifest.xml, na tag <application>, defina a flag android:enableOnBackInvokedCallback como true.

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

Se você não informar um valor, o padrão vai ser false e vai ocorrer o seguinte:

  • A animação do sistema do gesto de volta preditivo será desativada.
  • O OnBackInvokedCallback será ignorado, mas as chamadas de OnBackPressedCallback vão continuar funcionando.

Ativar no nível da atividade

No Android 14 e versões mais recentes, a flag android:enableOnBackInvokedCallback permite ativar animações preditivas do sistema no nível da atividade. Esse comportamento facilita a migração de apps grandes com várias atividades para gestos de volta preditivos.

O código abaixo mostra um exemplo de como usar o enableOnBackInvokedCallback para ativar a animação do sistema de volta à tela inicial da MainActivity:

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

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

No exemplo anterior, definir android:enableOnBackInvokedCallback=true para ".SecondActivity" ativa a animação do sistema entre atividades.

Lembre-se das considerações abaixo ao usar a flag android:enableOnBackInvokedCallback:

  • Configurar android:enableOnBackInvokedCallback=false desativa as animações de volta preditiva no nível da atividade ou do app, dependendo de onde a tag foi definida. Além disso, instrui o sistema a ignorar chamadas para a API da plataforma OnBackInvokedCallback. No entanto, as chamadas para OnBackPressedCallback continuam sendo executadas porque OnBackPressedCallback é compatível com versões anteriores e chama a API onBackPressed, que não tem suporte em versões anteriores ao Android 13.
  • Definir a flag enableOnBackInvokedCallback no nível do app estabelece o valor padrão para todas as atividades nele. Você pode substituir o padrão por atividade definindo a flag no nível da atividade, conforme mostrado no exemplo de código anterior.

Práticas recomendadas de callback

Confira as práticas recomendadas para usar os callbacks de sistema com suporte: BackHandler (para Compose), OnBackPressedCallback ou OnBackInvokedCallback.

Determinar o estado da interface que ativa e desativa cada callback

O estado da interface é a propriedade que a descreve. Recomendamos seguir estas etapas gerais.

  1. Determine o estado da interface que ativa e desativa cada callback.

  2. Defina esse estado usando um tipo de detentor de dados observáveis, como StateFlow ou o estado do Compose, e ative ou desative o callback quando o estado mudar.

Se o app estava associando a lógica de retorno às instruções condicionais, isso pode significar que você está reagindo ao evento de retorno depois que ele já ocorreu. Evite essa situação em novos callbacks. Se possível, retire o callback da instrução condicional e associe-o a um tipo de detentor de dados observáveis.

Usar callbacks de sistema para a lógica da interface

A lógica da interface determina como mostrá-la. Use callbacks de sistema para executar a lógica da interface, como exibir um pop-up ou executar uma animação.

Se o app ativar um callback de sistema, as animações preditivas não serão executadas, e você vai precisar processar o evento de retorno. Não crie callbacks apenas para executar uma lógica que não seja da interface.

Por exemplo, se você estiver interceptando eventos de retorno apenas para geração de registros, faça os registros no ciclo de vida da atividade ou do fragmento.

  • Para casos atividade-atividade ou fragmento-atividade, registre se isFinishing em onDestroy for true no ciclo de vida da atividade.
  • Para casos fragmento-fragmento, registre se isRemoving em onDestroy for verdadeiro no ciclo de vida da visualização do fragmento ou use os métodos onBackStackChangeStarted ou onBackStackChangeCommitted em FragmentManager.OnBackStackChangedListener.

Para o caso do Compose, faça o registro no callback onCleared() de um ViewModel associado ao destino do Compose. Esse é o melhor sinal para saber quando um destino do Compose foi retirado da backstack e destruído.

Criar callbacks de responsabilidade única

Isso é possível porque você pode adicionar vários callbacks ao agente. Eles são adicionados a uma pilha em que o último callback ativo adicionado processa o próximo gesto de volta com um callback por gesto de volta.

Testar a animação do gesto de volta preditivo

Na versão final do Android 13 e mais recentes, você vai poder ativar uma opção para desenvolvedores para testar a animação de retorno à tela de início, conforme mostrado na Figura 1.

Para testar a animação, siga estas etapas:

  1. No dispositivo, acesse Configurações > Sistema > Opções do desenvolvedor.

  2. Selecione Animações de gestos "Voltar" preditivos.

  3. Inicie o app atualizado e use o gesto "Voltar" para testar o recurso.