Os usuários navegam para trás nas telas usando a navegação de retorno. A maioria dos dispositivos Android tem um botão "Voltar" (físico, de software ou baseado em gestos). Normalmente, não é necessário adicionar um botão "Voltar" ao seu app. No entanto, os dispositivos Android Automotive OS (AAOS) no modo de compatibilidade usam um botão "Voltar" do sistema. Isso processa a navegação, então não é necessário adicionar seu próprio botão. Para mais detalhes, consulte Modo de compatibilidade do AAOS.
O Android mantém uma backstack de destinos à medida que o usuário navega no seu app. Isso normalmente permite que o Android navegue
adequadamente para destinos anteriores quando o botão "Voltar" é pressionado. No entanto, há
casos em que seu app precisa implementar um comportamento de retorno próprio para
fornecer a melhor experiência do usuário possível. Por exemplo, ao usar uma WebView, convém modificar o comportamento padrão do botão "Voltar" para permitir que o usuário navegue de volta pelo histórico de navegação da Web em vez das telas anteriores no seu app.
Implementar a navegação de retorno personalizada no Compose
No Jetpack Compose, é possível processar a navegação de retorno personalizada usando o
BackHandler elemento combinável.
Ao usar Navigation Compose, normalmente você usa
NavController.navigateUp() ou NavController.popBackStack()
para navegar até a tela anterior na backstack. No entanto, BackHandler é útil para casos em que você quer implementar um comportamento personalizado quando o usuário pressiona o botão "Voltar" do sistema ou usa o gesto de retorno. Por exemplo, se você
estiver mostrando um WebView no seu app, talvez queira permitir que os usuários
naveguem de volta pelo histórico de navegação quando pressionarem o botão "Voltar" do sistema.
Uso básico
Confira um exemplo de como interceptar o evento de retorno para controlar o estado personalizado (como recolher um painel):
@Composable fun MyScreen() { var isExpanded by remember { mutableStateOf(false) } // Intercept the back button or gesture only when isExpanded is true BackHandler(enabled = isExpanded) { // Collapsing the content disables this handler, so it does not // receive the next back event. isExpanded = false } if (isExpanded) { Text("Expanded content. Go back to collapse it.") } else { Button(onClick = { isExpanded = true }) { Text("Expand") } } }
Interceptação da árvore de elementos combináveis
Se você tiver vários elementos combináveis BackHandler ativados em diferentes níveis da árvore de elementos combináveis, apenas o mais interno interceptará o evento de retorno.
Implementar a navegação de retorno personalizada com visualizações
ComponentActivity, a classe de base para FragmentActivity e
AppCompatActivity, permite controlar o comportamento do botão "Voltar"
usando o OnBackPressedDispatcher, que pode ser recuperado chamando
getOnBackPressedDispatcher().
O OnBackPressedDispatcher controla como os eventos do botão "Voltar" são enviados
para um ou mais objetos OnBackPressedCallback. O construtor de OnBackPressedCallback usa um booleano para o estado ativado inicial. Somente quando
um callback está ativado, por exemplo, quando isEnabled() retorna true, o
dispatcher chama handleOnBackPressed() do callback para processar o
evento do botão "Voltar". Você pode alterar o estado ativado chamando
setEnabled().
Os callbacks são adicionados usando os métodos addCallback. Use o
addCallback() método, que usa um LifecycleOwner. Dessa forma, o
OnBackPressedCallback só é adicionado quando o LifecycleOwner é
Lifecycle.State.STARTED. A atividade também remove os callbacks registrados quando o LifecycleOwner associado é destruído, o que evita vazamentos de memória e o torna adequado para uso em fragmentos ou outros proprietários de ciclo de vida que têm um tempo de vida mais curto do que a atividade.
Veja um exemplo de implementação de callback:
class MyFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // This callback will only be called when MyFragment is at least Started. val callback = requireActivity().onBackPressedDispatcher.addCallback(this) { // Handle the back button event } // The callback can be enabled or disabled here or in the lambda } ... }
É possível fornecer vários callbacks usando addCallback().
Ao fazer isso, os callbacks são invocados na ordem inversa em que são adicionados. O callback adicionado por último é o primeiro a ter a chance de processar o evento do botão "Voltar". Por exemplo, se você adicionou três callbacks chamados one, two e three em ordem, eles seriam invocados na ordem de three, two e one, respectivamente.
Os callbacks seguem o
padrão Cadeia de responsabilidade. Cada callback na cadeia é invocado apenas se o callback anterior não estiver ativado. Isso significa que, no exemplo anterior, o callback two seria invocado apenas se o callback three não estivesse ativado. O callback one só seria invocado se o callback two não estivesse ativado, e esse padrão continua para outros callbacks.
Quando adicionado usando addCallback(),
o callback não é adicionado à cadeia de responsabilidade até que o
LifecycleOwner entre no estado
Lifecycle.State.STARTED.
É altamente recomendável mudar o estado ativado no callback para mudanças temporárias, porque ele mantém a ordem descrita anteriormente, o que é particularmente importante se você tiver callbacks registrados em vários proprietários de ciclo de vida aninhados diferentes.
Se você quiser remover o callback completamente, chame
remove().
Isso geralmente não é necessário porque os callbacks são automaticamente
removidos quando o LifecycleOwner associado é destruído.