如何在 Jetpack Compose 中使底部导航与屏幕到屏幕导航协同工作?

问题描述 投票:0回答:1

我实现了一个底部栏,可导航到四个不同的屏幕:“主页”、“收藏夹”、“已听”和“关于”。我还实现了与底部栏分开的导航,您可以从“主页”转到“更多页面”。下面是导航的草图:

enter image description here

当您打开应用程序时,底部栏导航将起作用;我可以在导航栏屏幕之间正常导航;但是当我尝试导航到“更多屏幕”时,应用程序崩溃了。以下是我得到的错误:

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并在过去的两天里一直尝试在我自己的项目中实现它,但因为我对此非常陌生我并没有走得太远。任何指向正确方向的指针都意义重大!

android kotlin navigation android-jetpack-compose
1个回答
0
投票

您应该将底部导航从

NavHost
中删除 你的应用程序的层次结构应该是这样的:

  • SomeScreen()

    |

    • NavHost()

    |

    • 底部导航()
© www.soinside.com 2019 - 2024. All rights reserved.