Navigation
Navigation
Section titled “Navigation”El Navigation component utilitza un graf de navegació per gestionar la navegació de la teva aplicació.
El graf de navegació és la estructura de dades que conté cada destinació dins la teva aplicació i la conexió entre elles.
Note: The navigation graph is distinct from the back stack, which is a stack within the NavController
that holds destinations the user has recently visited.
Hi ha tres tipus de destinacions: hosted, dialog, i activity.
Les destinacions “hosted” són les que s’utlitzen amb més freqüència, i ocupen tota la pantalla del host.
Hosted destinations are the most common and fundamental destinations.
Project de suport: https://gitlab.com/xtec/kotlin/compose/navigation/
Entorn de treball
Section titled “Entorn de treball”Crea un nou projecte compose-navigation
amb amb Kotlin Multiplatform wizard.
Obre el fitxer composeApp/build.gradle.kts
.
En la secció plugins
, afegeix el plugin plugin.serialization
:
plugins { kotlin("plugin.serialization") version "2.1.0" // ...}
En la secció `commonMain.dependencies`, afegeix la dependència amb `navigation-compose` i `kotlinx-serialization-json`:
```ktdependencies { implementation("org.jetbrains.androidx.navigation:navigation-compose:2.8.0-alpha10") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") // ...}
Navegació
Section titled “Navegació”A continuació tens una aplicació d’exemple amb dos pantalles (“screens”).
Modifica el fitxer composeApp/src/commonMain/kotlin/dev/xtec/App.kt
:
package dev.xtec
import androidx.compose.foundation.layout.Columnimport androidx.compose.material.Buttonimport androidx.compose.material.MaterialThemeimport androidx.compose.material.Textimport androidx.compose.runtime.*
import androidx.navigation.NavControllerimport androidx.navigation.compose.NavHostimport androidx.navigation.compose.composableimport androidx.navigation.compose.rememberNavControllerimport kotlinx.serialization.Serializable
@Composablefun App() { MaterialTheme { val controller = rememberNavController() NavHost(controller, startDestination = HomeRoute) { composable<HomeRoute> { HomeScreen(controller) } composable<CityRoute> { CityScreen() } } }}
@Serializableobject HomeRoute
@Composablefun HomeScreen(controller: NavController) {
Column { Text("Home") Button(onClick = { controller.navigate(CityRoute) }) { Text("City") } }}
@Serializableobject CityRoute
@Composablefun CityScreen() { Text("Barcelona")}
Amb la funció “composable” NavHost
crees un graf de navegació.
Al cridar la funció “composable” NavHost
passem com a paràmetres un NavController
i una ruta pel destí incial (la ruta Home
).
Amb la funció composable()
defineixes quin “composable” es el destí d’una “ruta”.
flowchart LR home([HomeRoute]) --> HomeScreen city([CityRoute"]) --> CityScreen
Quan defineixes una ruta mai has de dir de quin “screen” ha de venir, sinó quin “screen” a de gestionar la “ruta”:
Activitat
Section titled “Activitat”1.- Afegeix un nova pàgina CountryScreen
.
{% sol %}
@Composablefun App() { val controller = rememberNavController() NavHost(controller, startDestination = HomeRoute) { composable<HomeRoute> { HomeScreen(controller) } composable<CityRoute> { CityScreen() composable<CountryRoute> { CountryScreen() } } }}
@Serializableobject CountryRoute
@Composablefun CountryScreen() { Text("Country")}
{% endsol %}
2.- Afegeix un botó a HomeScreen
que et porti a CountryScreen
.
{% sol %}
@Composablefun HomeScreen(controller: NavController) {
Column { Text("Home") Button(onClick = { controller.navigate(CityRoute) }) { Text("City") } Button(onClick = { controller.navigate(CountryRoute) }) { Text("Country") } }}
{% endsol %}
3.- Afegeix un botó a CountryScreen
que et porti a CiytScreen
.
{% sol %}
@Composablefun HomeScreen(controller: NavController) {
Column { Text("Home") Button(onClick = { controller.navigate(CityRoute) }) { Text("City") } Button(onClick = { controller.navigate(CountryRoute) }) { Text("Country") } }}
{% endsol %}
4.- Afegeix una barra de navegació (TopAppBar
):
{% sol %}
@Composablefun Nav(controller: NavController) { TopAppBar( title = { Text("Geography") }, actions = { IconButton(onClick = { controller.navigate(HomeRoute) }) { Icon(imageVector = Icons.Filled.Home, contentDescription = "Home") } } )}
@Composablefun HomeScreen(controller: NavController) {
Column { Nav(controller) Button(onClick = { controller.navigate(CityRoute) }) { Text("City") } Button(onClick = { controller.navigate(CountryRoute) }) { Text("Country") } }}
// ...
{% endsol %}
Paràmetres
Section titled “Paràmetres”Si vols passar paràmetres a un “screen” has d’utlitzar un data class
enlloc d’un object
.
@Serializabledata class CityRoute(val name: String)
Ara el component HomeScreen
ja pot utilitzar la nova ruta:
@Composablefun HomeScreen(controller: NavController) {
// ... Button(onClick = { controller.navigate(CityRoute("Girona")) }) { Text("City") } // ... }}
El NavHost
ha de configurar la ruta passant CityRoute
a CityScreen
:
@Composablefun App() { MaterialTheme { val controller = rememberNavController() NavHost(controller, startDestination = HomeRoute) { composable<HomeRoute> { HomeScreen(controller) } composable<CityRoute> { entry -> CityScreen(controller, entry.toRoute()) } composable<CountryRoute> { CountryScreen(controller) } } }}
El component CityScreen
ha d’acceptar com a paràmetre CityRoute
:
@Composablefun CityScreen(controller: NavController, route: CityRoute) { Column { Nav(controller) Text(route.name) }}
Ara CityScreen
mostra la ciutat que li passen com a paràmetre.
Activitat
Section titled “Activitat”1.- Afegeixt un TextField
a HomeScreen
on l’usuari pugui posar la ciutat que vulgui i al apretar el botó passi el contigut com a paràmtre
{% sol %}
@Composablefun HomeScreen(controller: NavController) {
// ... Row( modifier = Modifier.padding(8.dp) ) { TextField( value = city.value, placeholder = { Text("City Name") }, onValueChange = { city.value = it }) Button( onClick = { controller.navigate(CityRoute(city.value)) } ) { Text("City View") } } // ... }}
{% endsol %}
Activitats
Section titled “Activitats”1.- Crea un “screen” Countries
que mostri una llista de paisos:
{% sol %}
val countries = listOf("Spain", "France", "Italy", "Portugal", "Germany")
@Serializableobject CountryListRoute
@Composablefun CountryListScreen(controller: NavController) { Column { Nav(controller) LazyColumn() { items(countries) { country -> Text(text = country) } } }}
{% endsol %}
2.- Afageix un enllaç del “screen” a la barra de navegació
{% sol %}
@Composablefun Nav(controller: NavController) { TopAppBar( title = { Text("Geography") }, actions = { IconButton(onClick = { controller.navigate(HomeRoute) }) { Icon(imageVector = Icons.Filled.Home, contentDescription = "Home") } IconButton(onClick = { controller.navigate(CountryListRoute) }) { Text("Countries") } } )}
{% endsol %}
3.- Fes que la llista de països sigui clicable i navegui al “screen” Country
:
{% sol %}
@Composablefun CountryListScreen(controller: NavController) { Column { Nav(controller) LazyColumn() { items(countries) { country -> Row( modifier = Modifier.clickable { controller.navigate(CountryRoute(country)) } .padding(4.dp) .border(1.dp, color = MaterialTheme.colors.primary, CircleShape) .padding(4.dp).fillMaxWidth() ) { Text(text = country) } } } }}
{% endsol %}
4.- Fes el mateix amb un “screen” Cities
.
-
https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-navigation-routing.html
-
https://devblogs.dashwave.io/debugging-crash-issues-in-android-app
-
https://developer.android.com/guide/navigation/design/type-safety
-
https://medium.com/@jpmtech/navigation-in-jetpack-compose-c9e1fcfd2cdd
-
https://developer.android.com/codelabs/jetpack-compose-navigation
El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.
©2022-2025 xtec.dev