Criando Alert Dialogs com Navigation - Jetpack Compose
Introdução
O Jetpack Compose é uma biblioteca de UI do Android que permite a criação de interfaces de usuário reativas e intuitivas. Um dos recursos mais importantes do Compose é o Navigation, que permite a navegação fluida entre as telas do aplicativo.
Neste artigo, vamos mostrar como criar Alert Dialogs personalizados no Navigation, para tornar a experiência do usuário mais ágil e nosso código mais eficiente e reutilizável. Abaixo, você tem um exemplo da tela que iremos criar:
Conhecendo o projeto
O projeto a ser utilizado é um App de restaurante que oferece diversas formas de visualização do cardápio, através de uma barra inferior de navegação com destaques, menu e bebidas, podendo também efetuar pedidos e escolher formas de pagamento, conforme exemplo abaixo:
Esse código foi feito no curso de Jetpack Compose: navegando entre telas com o Navigation, aqui da Alura, e você pode acessar o código neste link.
Se você é novo esse assunto e ainda não tem familiaridade com o Navigation do compose, recomendo que acesse a documentação oficial de navegação e faça os cursos disponíveis na plataforma da Alura sobre o tema.
Fluxo de Dialogs otimizado com o Navigation
Vamos partir do seguinte contexto: É preciso que ao clicar no botão “pedir” na tela de destaques, apareça uma solicitação de confirmação perguntando se gostaríamos de ir direto para o pagamento ou continuar comprando. Com esse contexto, qual seria a melhor forma de implementar essa tarefa?
Podemos dizer que teríamos várias formas de implementar essa atividade, e vamos destacar as consideradas mais comuns:
- Navegar para uma tela completa de “Continuar comprando” com algumas opções, sem nenhum sobreposição; mas isso pode não ser necessário com poucas opções;
- Outra forma seria utilizar o Dialogs do Compose para questões objetivas, como confirmação ou cancelamento.
E essa última é a que vamos utilizar juntamente com algumas facilidades do Navigation, conforme exemplo abaixo:
Se quiser saber mais sobre Dialogs, acesse o artigo Utilizando Dialogs no Jetpack Compose para exibir mensagens ao usuário.
Agora que você já conhece nossa proposta e tem acesso ao projeto, vamos para a prática!
Implementando com o Navigation
Aqui teremos um exemplo de como fazer essa implementação, mas você pode implementar da forma que achar melhor e colocar as funcionalidades que preferir. Dito isso, vamos lá.
Criando o Dialog
Vamos começar criando o componente visual do nosso Alert Dialog:
1) Crie um composable dentro da pasta components com o nome que preferir. Aqui vou utilizar o nome DialogOrderConfirmation
;
2) Você pode utilizar o composable AlertDialog
do próprio compose, para estilizar mais rápido:
@Composable
fun OrderConfirmationDialog(
onConfirmButton: () -> Unit = {},
onDismissButton: () -> Unit = {},
onDismissRequest: () -> Unit = {}
) {
AlertDialog(
onDismissRequest = { onDismissRequest() },
confirmButton = { TextButton(onClick = { onConfirmButton() }) {
Text(text = "Ir para sacola")
} },
dismissButton = { TextButton(onClick = { onDismissButton() }) {
Text(text = "Continuar compra")
} },
icon = { Icon(Icons.Default.Shop, null) },
title = { Text(text = "Itens adicionados")},
text = { Text(text = """
1x - Lorem ipsum dolor sit amet
Deseja ir para as formas de pagamento na sacola ou continuar comprando?
""".trimIndent()) }
)
}
3) Como resultado visual, você terá este dialog:
Implementando rota
Agora é preciso criar uma rota para esse Dialog:
1) Vá na pasta navigation > AppDestination.kt
2) Dentro da classe AppDestination
, inclua no final do seu corpo a linha referente à rota do nosso dialog:
sealed class AppDestination(val route: String) {
... código omitido
object OrderConfirmationDialog : AppDestination("orderConfirmationDialog")
}
3) Em seguida, na MainActivity
dentro de NavHost
ao invés de colocar a chamada decomposable(…)
, utilize uma específica para Dialogs no Navigation e insira nosso composable de Dialog nela:
NavHost(
navController = navController,
startDestination = AppDestination.Highlight.route
) {
... código omitido
dialog(AppDestination.OrderConfirmationDialog.route) {
OrderConfirmationDialog(
onConfirmButton = { navController.navigate(AppDestination.Checkout.route) },
onDismissButton = { navController.popBackStack() },
onDismissRequest = { navController.popBackStack() },
)
}
}
É interessante destacar que quando colocamos um composable dentro da chamada de dialog(…) { }
, temos alguns comportamentos interessantes para os Dialogs, como o fato de que se após navegarmos ao Checkout quando clicamos em “ir para sacola”, e ocasionalmente apertarmos para voltar dentro da tela de Checkout, não somos redirecionados para o Dialog. Isso acontece porque ele é retirado automaticamente da backStack
ao utilizarmos as chamadas do Navigation corretamente.
Caso utilize a chamada de composable(…)
ao invés de dialog(…)
, teremos alguns comportamentos que não condizem com os Dialogs, como por exemplo:
- Ele navega para uma tela específica somente com o Dialog, ou seja, você não será capaz de ver o contexto em que o Dialog foi iniciado;
- Caso faça o processo de voltar na tela de Checkout, ele vai voltar para a tela de Dialog, coisa que prejudica o fluxo do App e a experiência do usuário colocando muitas ações repetitivas.
Se quiser, faça o teste substituindo as chamadas e veja o que acontece.
Seguindo os passos corretamente, você chegará neste resultado:
Como uma boa prática, dentro do nosso composable HighlightsListScreen
faça uma alteração semântica na ação de onNavigateToCheckout
, no caso faça a alteração do nome da ação para: onNavigateToOrderConfirmation
e ao invés de usar a rota para o Checkout, use a rota para o Dialog, desta forma:
composable(AppDestination.Highlight.route) {
HighlightsListScreen(
products = sampleProducts,
onNavigateToDetails = { product ->
navController.navigate(
"${AppDestination.ProductDetails.route}/${product.id}"
)
},
onNavigateToOrderConfirmation = {
// navController.navigate(AppDestination.Checkout.route)
navController.navigate(AppDestination.OrderConfirmationDialog.route)
},
)
}
Conclusão
Neste artigo, aprendemos como os Dialogs são implementados juntamente da biblioteca de Navigation do Jetpack Compose. Através dessa técnica conseguimos fazer um fluxo de navegação mais fluído tanto para a pessoa que usa o App quanto para a pessoa desenvolvedora, que conta com uma melhor usabilidade do app e a personalização mais simplificada.
Se você se interessou pelo tema e quer ser aprofundar ainda mais em Android, recomendamos a formação: Jetpack Compose: criando telas e gerenciando estados, como também o curso Jetpack Compose: Navegando entre telas com o Navigation.
Continue mergulhando com a gente e até a próxima!