|
package com.example.navigation |
|
|
|
import android.os.Parcelable |
|
import androidx.compose.material.Scaffold |
|
import androidx.compose.runtime.Composable |
|
import androidx.compose.runtime.getValue |
|
import androidx.compose.runtime.remember |
|
import androidx.compose.ui.Modifier |
|
import androidx.navigation.NavBackStackEntry |
|
import androidx.navigation.NavHostController |
|
import androidx.navigation.compose.NavHost |
|
import androidx.navigation.compose.composable |
|
import androidx.navigation.compose.currentBackStackEntryAsState |
|
import androidx.navigation.compose.rememberNavController |
|
import androidx.navigation.navigate |
|
import androidx.navigation.rememberRequiredArgument |
|
import androidx.navigation.routeName |
|
import kotlinx.parcelize.Parcelize |
|
|
|
@Parcelize |
|
data class UserDetails( |
|
val firstName: String, |
|
val lastName: String, |
|
val emailAddress: String, |
|
val age: Int, |
|
) : Parcelable |
|
|
|
enum class Route { |
|
USER_DETAILS_FORM, |
|
USER_DETAILS_CONFIRM; |
|
|
|
companion object { |
|
fun from(navBackStackEntry: NavBackStackEntry?): Route? = |
|
navBackStackEntry.routeName?.let { routeName: String -> |
|
try { |
|
valueOf(routeName) |
|
} catch (e: IllegalArgumentException) { |
|
null |
|
} |
|
} |
|
} |
|
} |
|
|
|
@Composable |
|
fun NavigationExample() { |
|
val navController: NavHostController = rememberNavController() |
|
// these 2 are optional, but useful for when you want to detect the current screen and possibly set the |
|
// route name in the topBar composable of the Scaffold. |
|
val currentBackStackEntry: NavBackStackEntry? by navController.currentBackStackEntryAsState() |
|
val currentRoute: Route? = remember(currentBackStackEntry?.id) { Route.from(currentBackStackEntry) } |
|
Scaffold( |
|
topBar = { |
|
// You can use the currentRoute here to add some title for each route |
|
} |
|
) { |
|
NavHost( |
|
navController = navController, |
|
startDestination = Route.USER_DETAILS_FORM.name, |
|
) { |
|
composable(Route.USER_DETAILS_FORM.name) { |
|
UserDetailsForm( |
|
onReadyToReviewClicked = { userDetails: UserDetails -> |
|
navController.navigate( |
|
route = Route.USER_DETAILS_CONFIRM.name, |
|
// passing the parcelable UserDetails as a nav arg |
|
arg = userDetails, |
|
) |
|
} |
|
) |
|
} |
|
composable(Route.USER_DETAILS_CONFIRM.name) { navBackStackEntry: NavBackStackEntry -> |
|
// use the NavBackStackEntry parameter in the lambda to access the UserDetails nav arg |
|
// since it's a required (non optional) nav arg of this screen, use the rememberRequiredArgument() extension: |
|
val userDetails: UserDetails = navBackStackEntry.rememberRequiredArgument() |
|
UserDetailsConfirm( |
|
userDetails = userDetails, |
|
onConfirmUserDetailsClicked = { |
|
// TODO: for example, POST the details to some endpoint |
|
} |
|
) |
|
} |
|
} |
|
} |
|
} |
|
|
|
@Composable |
|
fun UserDetailsForm( |
|
onReadyToReviewClicked: (userDetails: UserDetails) -> Unit, |
|
modifier: Modifier = Modifier, |
|
) { |
|
// TODO: 1. add editable form UI fields, also some 'review' button |
|
// TODO: 2. store form data in mutable states for each field in the form |
|
// TODO: 3. call onReadyToReviewClicked in the 'review' button's onClick, |
|
// with a UserDetails object (build it from the multiple mutable states that are populated by the form) |
|
|
|
} |
|
|
|
@Composable |
|
fun UserDetailsConfirm( |
|
userDetails: UserDetails, |
|
onConfirmUserDetailsClicked: () -> Unit, |
|
modifier: Modifier = Modifier, |
|
) { |
|
// TODO: 1. add stateless UI (as in UI they can't change like in UserDetailsForm) using the passed in UserDetails, including some 'confirm' button |
|
// TODO: 2. call onConfirmUserDetailsClicked in the 'confirm' button's onClick |
|
} |
I got these errors