El component de navegació fa servir un graf de navegació per gestionar la navegació de la teva aplicació.
Navigation
El Navigation component utilitza un graf de navegadió 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 pantall del host.
Hosted destinations are the most common and fundamental destinations.
Entorn de treball
Obre el fitxer app/build.gradle.kts
.
En la secció dependencies
, afegeix la dependència amb navigation-compose
:
dependencies {
implementation("androidx.navigation:navigation-compose:2.8.4")
// ...
}
Pots trobar l'última versió de navigation-compose
en aquest enllaç: here.
També has d'afegir les dependències de Serialització.
Navegació
A continuació tens una aplicació d'exemple amb dos pantalles ("screens"):
package dev.xtec.composenavigation
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import kotlinx.serialization.Serializable
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
App()
}
}
}
@Composable
fun App() {
val controller = rememberNavController()
NavHost(controller, startDestination = HomeRoute) {
composable<HomeRoute> { HomeScreen(controller) }
composable<CityRoute> { CityScreen }
}
}
@Serializable
object HomeRoute
@Composable
fun HomeScreen(controller: NavController) {
Column {
Text("Home")
Button(onClick = {controller.navigate(CityRoute)}) {
Text("City")
}
}
}
@Serializable
object CityRoute
@Composable
fun 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
1.- Afegeix un nova pàgina CountryScreen
.
@Composable
fun App() {
val controller = rememberNavController()
NavHost(controller, startDestination = HomeRoute) {
composable<HomeRoute> { HomeScreen(controller) }
composable<CityRoute> { CityScreen(controller)
composable<CountryRoute> { CountryScreen() }
}
}
}
@Serializable
object CountryRoute
@Composable
fun CountryScreen() {
Text("Country")
}
2.- Afegeix un botó a HomeScreen
que et porti a CountryScreen
.
@Composable
fun HomeScreen(controller: NavController) {
Column {
Text("Home")
Button(onClick = { controller.navigate(CityRoute) }) {
Text("City")
}
Button(onClick = { controller.navigate(CountryRoute) }) {
Text("Country")
}
}
}
3.- Afegeix un botó a CountryScreen
que et porti a CiytScreen
.
Paràmetres
Si vols passar paràmetres a un "screen" has d'utlitzar un data class
enlloc d'un object
.
@Serializable
data class CityRoute(val name: String)
Ara el component HomeScreen
ja pot utilitzar la nova ruta:
@Composable
fun HomeScreen(controller: NavController) {
Column {
Text("Home")
Button(onClick = {controller.navigate(CityRoute("Girona"))}) {
Text("City")
}
}
}
El NavHost
ha de configurar la ruta passant CityRoute
a CityScreen
:
@Composable
fun App() {
val controller = rememberNavController()
NavHost(controller, startDestination = HomeRoute) {
composable<HomeRoute> { HomeScreen(controller) }
composable<CityRoute> { backStackEntry -> CityScreen(backStackEntry.toRoute())}
}
}
El component CityScreen
ha d'acceptar com a paràmetre CityRoute
:
@Composable
fun CityScreen(route: CityRoute) {
Text(route.name)
}
Ara CityScreen
mostra la ciutat que li passen com a paràmetre.
Activitat
1.- Afegeixt un TextField
a HomeScreen
on l'usuari pugui posar la ciutat que vulgui i al apretar el botó "City" passi el contigut com a paràmtre
PENDENT S'ha d'adaptar
@Composable
fun HomeScreen(controller: NavController) {
val city = remember { mutableStateOf("") }
Column() {
TextField(value = city.value, onValueChange = {
city.value = it
})
Button(onClick = {}) {
Text("City")
}
}
}
TODO
- https://devblogs.dashwave.io/debugging-crash-issues-in-android-app
- https://developer.android.com/studio/debug/logcat?hl=es-419
- https://developer.android.com/guide/navigation/design/type-safety
- https://developer.android.com/guide/navigation/design
- https://medium.com/@jpmtech/navigation-in-jetpack-compose-c9e1fcfd2cdd
- https://medium.com/@KaushalVasava/navigation-in-jetpack-compose-full-guide-beginner-to-advanced-950c1133740
- https://developer.android.com/codelabs/jetpack-compose-navigation