我实现了一个底部栏,可导航到四个不同的屏幕:“主页”、“收藏夹”、“已听”和“关于”。我还实现了与底部栏分开的导航,您可以从“主页”转到“更多页面”。下面是导航的草图:
当您打开应用程序时,底部栏导航将起作用;我可以在导航栏屏幕之间正常导航;但是当我尝试导航到“更多屏幕”时,应用程序崩溃了。以下是我得到的错误:
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/more_screen2130968599/0739 - Ready for the House/1978/Album/43:14/https:__www.youtube.com_watch?v=eAYs3sDcbbM/https:__corwoodindustries.com_product_0739_/false/NAKED IN THE AFTERNOON....
cannot be found in the navigation graph ComposeNavGraph(0x0) startDestination={Destination(0x442b361f) route=home_screen}
下面是我的 Navigation.kt 文件:
/**
* Nav graph
*/
package com.example.jandeksdiscography.navigation
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.jandeksdiscography.screens.FavoritePage
import com.example.jandeksdiscography.screens.InfoColumn
import com.example.jandeksdiscography.screens.JandekApp
import com.example.jandeksdiscography.screens.LyricsColumn
@Composable
fun SetupNavGraph(
navController: NavHostController
) {
NavHost(
navController = navController,
startDestination = Screen.HomePage.route,
enterTransition = { EnterTransition.None},
exitTransition = { ExitTransition.None},
) {
composable(
route = Screen.HomePage.route
) {
JandekApp(navController = navController)
}
composable(
route = Screen.MoreScreen.route,
arguments = listOf(
navArgument(COVER) {
type = NavType.IntType
},
navArgument(NAME) {
type = NavType.StringType
},
navArgument(YEAR) {
type = NavType.StringType
},
navArgument(TYPE) {
type = NavType.StringType
},
navArgument(DURATION) {
type = NavType.StringType
},
navArgument(LISTEN_LINK) {
type = NavType.StringType
},
navArgument(BUY_LINK) {
type = NavType.StringType
},
navArgument(IS_FAVORITE) {
type = NavType.BoolType
},
navArgument(LYRICS) {
type = NavType.StringType
})
) { entry ->
InfoColumn(
navController = navController,
cover = entry.arguments?.getInt(COVER),
name = entry.arguments?.getString(NAME),
year = entry.arguments?.getString(YEAR),
type = entry.arguments?.getString(TYPE),
duration = entry.arguments?.getString(DURATION),
listenLink = entry.arguments?.getString(LISTEN_LINK),
buyLink = entry.arguments?.getString(BUY_LINK),
lyrics = entry.arguments?.getString(LYRICS),
)
}
composable(
route = Screen.LyricsPage.route,
arguments = listOf(
navArgument(NAME) {
type = NavType.StringType
},
navArgument(LYRICS) {
type = NavType.StringType
}
)
) {entry ->
LyricsColumn(
navController = navController,
name = entry.arguments?.getString(NAME),
lyrics = entry.arguments?.getString(LYRICS),
modifier = Modifier
)
}
}
}
这是我的 BottomNavigationGraph.kt 文件:
@file:OptIn(ExperimentalMaterial3Api::class)
package com.example.jandeksdiscography.navigation
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.outlined.CheckCircle
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.jandeksdiscography.screens.AboutPage
import com.example.jandeksdiscography.screens.JandekApp
import com.example.jandeksdiscography.screens.FavoritePage
import com.example.jandeksdiscography.screens.ListenedPage
// List of bottom navigation bar items
val bottomNavItems = listOf(
BottomNavigationItem(
title = "HomePage",
route = Screen.HomePage.route,
selectedIcon = Icons.Filled.Home,
unselectedIcon = Icons.Outlined.Home,
),
BottomNavigationItem(
title = "Favorites",
route = Screen.Favorites.route,
selectedIcon = Icons.Filled.Favorite,
unselectedIcon = Icons.Outlined.FavoriteBorder,
),
/*
TODO: Import extended icons and try to find
a more suitable one for 'listened'
*/
BottomNavigationItem(
title = "Listened",
route = Screen.Listened.route,
selectedIcon = Icons.Filled.CheckCircle,
unselectedIcon = Icons.Outlined.CheckCircle,
),
BottomNavigationItem(
title = "About",
route = Screen.About.route,
selectedIcon = Icons.Filled.Info,
unselectedIcon = Icons.Outlined.Info,
),
)
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun BottomNavigationBar() {
// Implementation of the bottom navigation bar...
var selectedItemIndex by rememberSaveable {
mutableStateOf(0)
}
/*
Have to define the navController in the
BottomNavBar function
By using rememberNavController() we can get the instance
of the navController
*/
val navController = rememberNavController()
Surface (
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Scaffold (
bottomBar = {
NavigationBar {
// Loop through all the bottom navigation bar items
bottomNavItems.forEachIndexed { index, item ->
NavigationBarItem(
selected = selectedItemIndex == index,
onClick = {
selectedItemIndex = index
navController.navigate(item.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
label = { Text(text = item.title) },
icon = {
Icon(
imageVector =
if (index == selectedItemIndex) {
item.selectedIcon
} else item.unselectedIcon,
contentDescription = item.title
)
}
)
}
}
}
) {paddingValues->
NavHost(
navController = navController,
startDestination = Screen.HomePage.route,
enterTransition = {EnterTransition.None},
exitTransition = {ExitTransition.None},
modifier = Modifier.padding(paddingValues = paddingValues))
{
composable(Screen.HomePage.route) {
JandekApp(navController = navController)
}
composable(Screen.Favorites.route) {
FavoritePage(navController = navController)
}
composable(Screen.Listened.route) {
ListenedPage(navController = navController)
}
composable(Screen.About.route) {
AboutPage(navController = navController)
}
}
}
}
}
这是我的 Screen.kt 文件:
package com.example.jandeksdiscography.navigation
const val COVER = "cover"
const val NAME = "name"
const val YEAR = "year"
const val TYPE = "type"
const val DURATION = "duration"
const val LISTEN_LINK = "listenLink"
const val BUY_LINK = "buyLink"
const val LYRICS = "lyrics"
const val IS_FAVORITE = "isFavorite"
// Only allows classes in this file to inherit
sealed class Screen(val route: String) {
object HomePage: Screen("home_screen")
object MoreScreen: Screen("more_screen{$COVER}/{$NAME}/{$YEAR}/{$TYPE}/{$DURATION}/{$LISTEN_LINK}/{$BUY_LINK}/{$IS_FAVORITE}/{$LYRICS}") {
fun passArgs (
cover: Int,
name: String,
year: String,
type: String,
duration: String,
listenLink: String,
buyLink: String,
isFavorite: Boolean,
lyrics: String
): String {
return "more_screen$cover/$name/$year/$type/$duration/$listenLink/$buyLink/$isFavorite/$lyrics"
}
}
object LyricsPage: Screen("lyrics_page{$NAME}/{$LYRICS}") {
fun passLyrics (
name: String,
lyrics: String
): String {
return "lyrics_page$name/$lyrics"
}
}
object Favorites: Screen("favorites_screen")
object Listened: Screen("listened_screen")
object About: Screen("about_screen")
object NavHome: Screen("nav_home_screen")
}
我尝试遵循本教程https://www.youtube.com/watch?v=gNzPGI9goU0&t=110s并在过去的两天里一直尝试在我自己的项目中实现它,但因为我对此非常陌生我并没有走得太远。任何指向正确方向的指针都意义重大!
您应该将底部导航从
NavHost
中删除
你的应用程序的层次结构应该是这样的:
SomeScreen()
|
|