Jetpack Compose 在 Android 中组合导航和传递数据
几乎每个应用程序都使用某种导航,允许用户从一个屏幕移动到另一个屏幕。在本文中,我们将学习使用 Compose 方式在 Jetpack Compose 中实现导航。我们将构建一个简单的应用程序来演示 Jetpack 组合导航,它将具有三个屏幕(主页、配置文件和设置)。它将导航到带有一些数据的设置屏幕和没有任何数据的配置文件屏幕。下面给出了一个示例视频,以了解我们将在本文中做什么。
先决条件:
- Kotlin 的基础知识。
- Jetpack Compose 的知识。
分步实施
第 1 步:创建一个新项目(或在现有 Compose 项目中使用它)
要在 Android Studio Canary 版本中创建新项目,请参阅文章如何使用 Jetpack Compose 在 Android Studio Canary 版本中创建新项目。
第二步:添加依赖:
打开 build.gradle(app) 并在依赖项中添加这一行。
implementation “androidx.navigation:navigation-compose:2.4.0-alpha04”
第 3 步:创建路由
创建一个名为Routes的文件。添加以下代码。它将包含所有屏幕的路线名称。
Kotlin
// It contains route names to all three screens
sealed class Routes(val route: String) {
object Home : Routes("home")
object Profile : Routes("profile")
object Settings : Routes("setting")
}
Kotlin
@Composable
fun Home(navController: NavHostController) {
// Create a basic counter to display on screen
var counter by remember {
mutableStateOf(0)
}
// Box composable to center Items
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White), contentAlignment = Alignment.Center
) {
// A Column composable
Column {
// A Text Composable to show counter on Screen
Text(text = "Home, Counter is $counter", color = Color.Black)
Spacer(modifier = Modifier.height(20.dp))
// A button Composable which when clicked will increase the counter
Button(onClick = { counter++ }) {
Text(text = "Increment Counter", color = Color.White)
}
Spacer(modifier = Modifier.height(20.dp))
// A button composable to navigate to Profile Screen
Button(onClick = {
navController.navigate(Routes.Profile.route)
}) {
Text(text = "Navigate to Profile", color = Color.White)
}
Spacer(modifier = Modifier.height(20.dp))
// A Button Composable to navigate to
// Settings Screen when clicked
Button(onClick = {
navController.navigate(Routes.Settings.route + "/$counter")
}) {
Text(text = "Navigate to Settings", color = Color.White)
}
}
}
}
Kotlin
// Composable function which contains
// basic Composable functions
@Composable
fun Profile() {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White), contentAlignment = Alignment.Center
) {
Column {
Text(
text = "Navigation without arguments",
Modifier.padding(10.dp),
color = Color.Black
)
Text(text = "Profile Screen", Modifier.padding(10.dp), color = Color.Black)
}
}
}
Kotlin
// Settings Composable which receives counter as parameter
// passed down as arguments from home screen
@Composable
fun Setting(counter: String?) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White), contentAlignment = Alignment.Center
) {
Column {
Text(text = "Navigation with arguments", Modifier.padding(10.dp), color = Color.Black)
// Display the counter
Text(
text = "Settings Screen, passed data is $counter",
Modifier.padding(10.dp),
color = Color.Black
)
}
}
}
Kotlin
@Composable
fun ScreenMain() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Routes.Home.route) {
// First route : Home
composable(Routes.Home.route) {
// Lay down the Home Composable
// and pass the navController
Home(navController = navController)
}
// Another Route : Profile
composable(Routes.Profile.route) {
// Profile Screen
Profile()
}
// Settings Route, Notice the "/{id}" in last,
// its the argument passed down from homeScreen
composable(Routes.Settings.route + "/{id}") { navBackStack ->
// Extracting the argument
val counter = navBackStack.arguments?.getString("id")
// Setting screen,
// Pass the extracted Counter
Setting(counter = counter)
}
}
}
Kotlin
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Surface(color = MaterialTheme.colors.background) {
ScreenMain()
}
}
}
}
第 4 步:使用屏幕
它将有三个屏幕,所以我们需要创建三个可组合的。创建一个带有名称屏幕的包并创建三个文件(Home.kt、Profile.kt、Settings.kt)。使用主屏幕:
科特林
@Composable
fun Home(navController: NavHostController) {
// Create a basic counter to display on screen
var counter by remember {
mutableStateOf(0)
}
// Box composable to center Items
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White), contentAlignment = Alignment.Center
) {
// A Column composable
Column {
// A Text Composable to show counter on Screen
Text(text = "Home, Counter is $counter", color = Color.Black)
Spacer(modifier = Modifier.height(20.dp))
// A button Composable which when clicked will increase the counter
Button(onClick = { counter++ }) {
Text(text = "Increment Counter", color = Color.White)
}
Spacer(modifier = Modifier.height(20.dp))
// A button composable to navigate to Profile Screen
Button(onClick = {
navController.navigate(Routes.Profile.route)
}) {
Text(text = "Navigate to Profile", color = Color.White)
}
Spacer(modifier = Modifier.height(20.dp))
// A Button Composable to navigate to
// Settings Screen when clicked
Button(onClick = {
navController.navigate(Routes.Settings.route + "/$counter")
}) {
Text(text = "Navigate to Settings", color = Color.White)
}
}
}
}
使用配置文件屏幕:
科特林
// Composable function which contains
// basic Composable functions
@Composable
fun Profile() {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White), contentAlignment = Alignment.Center
) {
Column {
Text(
text = "Navigation without arguments",
Modifier.padding(10.dp),
color = Color.Black
)
Text(text = "Profile Screen", Modifier.padding(10.dp), color = Color.Black)
}
}
}
使用设置屏幕:
科特林
// Settings Composable which receives counter as parameter
// passed down as arguments from home screen
@Composable
fun Setting(counter: String?) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White), contentAlignment = Alignment.Center
) {
Column {
Text(text = "Navigation with arguments", Modifier.padding(10.dp), color = Color.Black)
// Display the counter
Text(
text = "Settings Screen, passed data is $counter",
Modifier.padding(10.dp),
color = Color.Black
)
}
}
}
第 5 步:使用 MainActivity 和导航组件
在MainActivity.kt 中创建一个名为 ScreenMain 的函数,该函数将包含 NavHost 和用于导航的 Composable。请参阅代码中的注释以更好地理解。
科特林
@Composable
fun ScreenMain() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Routes.Home.route) {
// First route : Home
composable(Routes.Home.route) {
// Lay down the Home Composable
// and pass the navController
Home(navController = navController)
}
// Another Route : Profile
composable(Routes.Profile.route) {
// Profile Screen
Profile()
}
// Settings Route, Notice the "/{id}" in last,
// its the argument passed down from homeScreen
composable(Routes.Settings.route + "/{id}") { navBackStack ->
// Extracting the argument
val counter = navBackStack.arguments?.getString("id")
// Setting screen,
// Pass the extracted Counter
Setting(counter = counter)
}
}
}
最后,在MainActivity 的onCreate 中从setContent调用这个 Composable 。
科特林
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Surface(color = MaterialTheme.colors.background) {
ScreenMain()
}
}
}
}
此外,您可以在使用 Compose Animation API 打开屏幕时添加动画。
输出:
从 Github 获取完整的项目。