Navigation Compose: o que é, arquitetura e trabalho no desenvolvimento

Autor: IT Sectr Publicado: 2026-06-29 Tempo de leitura: 8 min

Navigation Compose é uma biblioteca Jetpack para navegação declarativa dentro de aplicações Android construídas com Jetpack Compose. Em vez de FragmentManager ou navegação baseada em Intent, o Navigation Compose oferece um grafo de rotas único gerenciado através de NavController e NavHost. De acordo com o Google I/O (2025), o Navigation Compose é o método de navegação recomendado para aplicações Compose, usado em mais de 70% dos novos projetos. A biblioteca suporta passagem de argumentos tipados, links profundos, animações de transição e integração com ViewModel através do SavedStateHandle.

Principais pontos

  • Navigation Compose — uma biblioteca Jetpack para navegação declarativa em Compose com um grafo de rotas unificado
  • NavController — o controlador central que gerencia a pilha de navegação e o estado da pilha de retorno
  • NavHost — um contêiner que define o grafo de rotas através de funções composable com rota
  • Argumentos são passados via NavType e SavedStateHandle com suporte a parâmetros tipados
  • Links profundos — navegação através de URLs externas com análise automática de argumentos da URI

O que é Navigation Compose?

Navigation Compose é uma biblioteca do conjunto Jetpack que fornece um framework de navegação para aplicações Compose. A biblioteca é baseada nos mesmos princípios do Componente de Navegação para o sistema View, mas adaptada à natureza declarativa do Compose: em vez de FragmentTransaction, são usadas funções composable, e o grafo de navegação é construído via Kotlin DSL.

A principal diferença entre o Navigation Compose e a navegação clássica é a ausência do FragmentManager. Cada tela é uma função composable que é renderizada no NavHost quando a rota corresponde. A pilha de retorno armazena não um Fragment, mas um registro com rota, argumentos e estado. Isso simplifica a arquitetura e elimina os conflitos de ciclo de vida típicos da navegação baseada em Fragment.

De acordo com o Google (2025), o Navigation Compose passou de experimental para estável e faz parte do Jetpack desde a versão 2.8.0. A biblioteca suporta Material3, navegação type-safe (via Kotlin Serialization), grafos aninhados e modularização. A única limitação é que a biblioteca não suporta pilha de retorno múltipla para BottomNavigation sem configuração manual, embora o Google esteja trabalhando nisso.

A arquitetura do Navigation Compose gira em torno de três entidades: NavController (gerenciamento da pilha), NavHost (contêiner do grafo) e NavDestination (rota individual com composable). A interação entre elas é declarativa: o desenvolvedor descreve as rotas e os argumentos, e a biblioteca lida com os estados de carregamento, preservação e restauração.

NavController é o elemento central do Navigation Compose, que gerencia a pilha de navegação. É criado via rememberNavController() e passado para o NavHost. O NavController armazena a pilha de retorno, o ponto de entrada atual e suporta ações adiadas (deeplink após a inicialização do grafo).

kotlin
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "home") {
        composable("home") { HomeScreen(navController) }
        composable("profile/{userId}") { backStackEntry ->
            ProfileScreen(
                userId = backStackEntry.arguments?.getString("userId") ?: ""
            )
        }
    }
}

Principais métodos do NavController: navigate(route) — navegar para uma rota, popBackStack() — retornar à tela anterior, navigateAndClear(route) — navegar e limpar a pilha. NavOptions especificam o comportamento: launchSingleTop evita duplicatas, popUpTo limpa a pilha até a rota especificada, restoreState restaura o estado anterior.

Para acessar o NavController de funções composable profundamente aninhadas, use NavHostController através do CompositionLocal. O LocalNavController é fornecido no ScopedNavController dentro do NavHost. Fora do NavHost (por exemplo, no BottomNavigation), o controlador é passado através de parâmetros ou ViewModel.

NavHost é um contêiner composable que vincula o NavController ao grafo de rotas. Cada rota é declarada através de composable(route, arguments, deepLinks), onde route é uma string de rota com placeholders {param} opcionais. Quando a rota atual corresponde, o NavHost renderiza o bloco composable correspondente.

O grafo de rotas é construído hierarquicamente: os grafos podem ser aninhados através de navigation() para agrupar rotas dentro de um módulo. Grafos aninhados têm seu próprio startDestination e são combinados sob um prefixo de rota comum. Isso permite organizar uma arquitetura modular onde cada módulo de funcionalidade registra seu próprio subgrafo.

kotlin
NavHost(
    navController = navController,
    startDestination = "main"
) {
    composable("main") { MainScreen(navController) }
    navigation(
        route = "auth",
        startDestination = "auth/login"
    ) {
        composable("auth/login") { LoginScreen(navController) }
        composable("auth/register") { RegisterScreen(navController) }
    }
}

O NavHost lida automaticamente com o botão Voltar do sistema (back press) através do LocalBackDispatcher. No Material3 Scaffold, ele por padrão captura o NavController para a operação correta do BottomNavigation. O NavHost recria o composable quando a rota muda, mas preserva o estado através de rememberSaveable para campos de entrada e rolagem.

Passagem de argumentos entre telas

O Navigation Compose suporta a passagem de argumentos tipados entre telas através de parâmetros de rota e NavType. Os parâmetros são especificados na rota como {paramName} com o tipo indicado através de arguments em composable(). O NavType suporta String, Int, Long, Float, Boolean, Parcelable e Serializable.

Tipo de argumentoNavTypeExemplo de rota
StringNavType.StringType"profile/{name}"
IntNavType.IntType"item/{id}"
BooleanNavType.BoolType"settings?enabled={flag}"
ParcelableNavType.ParcelableType"details/{item}"
FloatNavType.FloatType"map?lat={lat}&lng={lng}"

Os argumentos são extraídos de NavBackStackEntry através de arguments?.getType(key). Para parâmetros obrigatórios use defaultValue, para opcionais — nullable. O suporte a Parcelable funciona apenas com Kotlin Parcelize ou a biblioteca kotlinx.parcelize. Para objetos complexos, é recomendado passar um ID e carregar dados através do ViewModel, em vez de serializar o objeto inteiro.

Desde o Navigation 2.8.0, foi introduzida a navegação type-safe com Kotlin Serialization: as rotas são definidas como classes de dados e os argumentos como campos. Isso substitui as rotas de string por objetos tipados e elimina erros nos nomes das rotas. A migração requer o plugin Kotlin Serialization e a dependência navigation-compose-typesafe.

kotlin
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
    data object Home : ProfileRoute("home")
    data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}

Links profundos é um mecanismo de navegação que permite abrir uma tela específica do aplicativo através de uma URL ou intent-filter. No Navigation Compose, os links profundos são configurados através do parâmetro deepLinks em composable() e são processados automaticamente quando a URI corresponde ao padrão.

Um link profundo é especificado como uma lista de UriPattern: "https://example.com/profile/{userId}". Os parâmetros da URI são mapeados automaticamente para os argumentos da rota. O NavController processa links profundos na inicialização do aplicativo (via intent) e durante a operação (via links profundos implícitos). Para lidar com links profundos pendentes, use handleDeepLink() no NavController após a inicialização do grafo.

De acordo com o Google, links profundos são recomendados para: notificações push (Firebase Dynamic Links), verificação de e-mail, compartilhamento de conteúdo e navegação cruzada a partir de links da web. Para Android 12+, são usados Digital Asset Links para verificar a autoridade do link profundo. O AndroidManifest.xml deve conter um intent-filter com autoVerify="true" para abrir links sem diálogo.

kotlin
composable(
    route = "profile/{userId}",
    arguments = listOf(navArgument("userId") { type = NavType.StringType }),
    deepLinks = listOf(
        navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
    )
) { backStackEntry ->
    ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}

Limitações dos links profundos no Navigation Compose: a biblioteca não suporta links profundos adiados — um link profundo é processado apenas depois que o NavHost construiu totalmente o grafo. Se um link profundo chegar antes da inicialização do grafo, ele deve ser adiado via intent?.data e processado no LaunchedEffect. Para Firebase Dynamic Links, use o Firebase Dynamic Links SDK junto com o Navigation Compose.

Animações de transição entre telas

O Navigation Compose suporta animações de transição através dos parâmetros enterTransition, exitTransition, popEnterTransition e popExitTransition em composable(). As animações são implementadas usando a Compose Animation API: fadeIn, slideInHorizontally, expandIn e outras. Por padrão, a animação está desativada — as telas são substituídas instantaneamente.

Cenários típicos de animação: slideInHorizontally para navegação para frente (a tela entra pela direita), slideOutHorizontally para retorno (a tela sai pela direita). Para BottomNavigation, a animação de desvanecimento sem deslizamento é mais comumente usada. As animações são definidas através do NavHost e se aplicam a todos os composables, a menos que animações individuais sejam especificadas.

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally() + fadeIn() },
    exitTransition = { slideOutHorizontally() + fadeOut() },
    popEnterTransition = { fadeIn() },
    popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }

As animações podem ser substituídas para cada composable individualmente passando parâmetros de animação diretamente em composable(). É importante que as animações não entrem em conflito com a animação de retorno do sistema. Para transição de elemento compartilhado, é necessária a biblioteca accompanist-navigation-animation ou uma implementação personalizada através de Modifier.graphicsLayer. De acordo com o Android Developers (2025), 80% dos aplicativos de produção usam animação de deslizamento horizontal para navegação padrão.

Perguntas frequentes

Como o Navigation Compose difere do Componente de Navegação para View?

Navigation Compose funciona sem Fragment, usando funções composable e Kotlin DSL para o grafo. O Componente de Navegação (View) é baseado em FragmentManager e grafos XML. A versão Compose é mais simples, mais rápida e não tem ciclos de vida de Fragment. O Componente de Navegação para View é adequado apenas para aplicações híbridas.

Como passar um objeto complexo entre telas?

É recomendado passar o ID do objeto e carregar os dados através do ViewModel com SavedStateHandle. Se o objeto for simples, use Parcelable via kotlinx.parcelize. Passar objetos grandes diretamente através de argumentos (Bundle) é limitado a ~1 MB e pode causar TransactionTooLargeException.

O Navigation Compose suporta grafos aninhados?

Sim, através da função navigation(route, startDestination) dentro do NavHost. Grafos aninhados têm seu próprio startDestination e são combinados sob um prefixo de rota comum. Isso permite organizar uma arquitetura modular com grafos isolados para cada módulo de funcionalidade.

Como lidar com o botão Voltar do sistema no Navigation Compose?

O NavController lida automaticamente com o pressionamento do botão Voltar através do BackHandler do Compose. Chame navController.popBackStack() quando Voltar for pressionado. Para tratamento personalizado (confirmação de saída), use BackHandler(enabled = condition) { callback } antes de chamar popBackStack().

Posso usar Navigation Compose com Jetpack Compose Multiplatform?

Atualmente, o Navigation Compose não é suportado no Compose Multiplatform. Para a parte iOS de projetos multiplataforma, use Voyager ou Decompose. O Google está trabalhando no suporte a KMP, mas não há previsão de lançamento. Para projetos apenas Android, o Navigation Compose é a única opção recomendada.

Resumo

  • Navigation Compose — uma biblioteca Jetpack para navegação declarativa em Compose, funcionando através de um grafo de rotas e NavController
  • NavController gerencia a pilha de retorno e fornece métodos navigate, popBackStack para navegação
  • NavHost vincula o controlador ao grafo via composable(), suportando grafos aninhados para arquitetura modular
  • Argumentos são passados via NavType com suporte para String, Int, Parcelable e navegação type-safe com Kotlin Serialization
  • Links profundos são configurados via navDeepLink com UriPattern para navegação externa a partir de URLs e notificações push
  • Animação de transições é definida via enterTransition, exitTransition usando a Compose Animation API
  • A biblioteca não suporta KMP e pilha de retorno múltipla para BottomNavigation sem configuração adicional

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também