android BottomNavigationBar中的Jetpack编写导航出现问题

ztmd8pv5  于 2023-03-06  发布在  Android
关注(0)|答案(2)|浏览(158)

根据下图,我的App目前包含2条主要路线:当用户启动应用程序时,观察者将检查用户是否已登录,并将其引导至登录页面/控制面板。
Navigation Flow
如图所示,我已经在主活动中设置了NavGraph(包括所有 Jmeter 板路线)。问题是,当用户单击底部导航项之一时,他/她将被直接定向到视图页面。相反,我想要向用户显示 Jmeter 板的scaffold内容中的视图。请检查下图。
Problem Encountered
基于这些信息,如何在用户单击该项时获得scaffold内容中的可组合视图?
任何指导将不胜感激。谢谢!

  • 旁注:这是我的第一个组合项目,我正在尝试实现单一活动架构,而不使用任何片段。我道歉之前,如果我的代码违反任何设计或编程约定,因为我是相当新的编程[自学者又名爱好者在这里:(]。*
    • 主要活动. kt**
package com.example.firstcomposeproject

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navigation
import com.example.firstcomposeproject.authview.FirebaseUserViewModel
import com.example.firstcomposeproject.authview.LogIn
import com.example.firstcomposeproject.authview.SignUpFragment
import com.example.firstcomposeproject.dashboard.*

import com.example.firstcomposeproject.ui.theme.FirstComposeProjectTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val userViewModel: FirebaseUserViewModel by viewModels()

        setContent {
            FirstComposeProjectTheme(
                darkTheme = false
            ) {
                val navController = rememberNavController()

                /*
                Observing FirebaseUser LiveData to check if user is logged in. If yes, direct user
                to dashboard, else direct user to authenticate screen.
                */
                userViewModel.userMutableLiveData.observe(this, {
                        firebaseUser ->
                    if(firebaseUser != null){
                        navController.popBackStack()
                        navController.navigate("dashboard"){
                            popUpTo("auth"){
                                inclusive = true
                            }
                        }

                        userViewModel.clearFormField()
                    }else {
                        navController.navigate("auth"){
                            popUpTo("dashboard"){
                                inclusive = true
                            }
                        }
                    }
                })

                //Navigation Graph For The Whole App
                NavHost(navController = navController, startDestination = "auth"){
                    navigation(startDestination = "logInUI", route = "auth"){
                        composable("logInUI"){
                            LogIn(
                                userViewModel,
                                onNavigate = {
                                    navigateTo(it, navController)
                                }
                            ).FinalView()
                        }

                        composable("signUpUI"){
                            SignUpFragment(
                                userViewModel,
                                onNavigate = {
                                    navigateTo(it, navController)
                                }
                            ).FinalView()
                        }
                    }
                    addDashBoardGraph(userViewModel, navController)
                }
            }
        }
    }

    private fun navigateTo(
        dest: String,
        navController: NavController
    ){
        navController.navigate(dest)
    }


}
    • Jmeter 板. kt**
package com.example.firstcomposeproject.dashboard

import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.navigation
import com.example.firstcomposeproject.authview.FirebaseUserViewModel
import com.example.firstcomposeproject.dashboard.helper.Screen

import com.example.firstcomposeproject.ui.theme.Teal200

fun NavGraphBuilder.addDashBoardGraph(
    userViewModel: FirebaseUserViewModel,
    navController: NavHostController
  ) {
    navigation(startDestination = "dashboardUI", route = "dashboard"){
        composable("dashboardUI"){
            Dashboard(
                navController,
                userViewModel
            )
        }

        composable("navigationUI"){
            Navigation()
        }

        composable("messageUI"){
            Message()
        }

        composable("historyUI"){
            History()
        }

        composable("profileUI"){
            Profile(
                userViewModel
            )
        }
    }
}

@Composable
fun Dashboard(
    navController: NavHostController,
    userViewModel: FirebaseUserViewModel
){
    val items = listOf(
        Screen.Navigation,
        Screen.Message,
        Screen.History,
        Screen.Profile
    )

    Scaffold(
        bottomBar = {
            BottomNavigation(
                backgroundColor = Color.White,
                contentColor = Teal200
            ) {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination

                items.forEach{ screen ->
                    BottomNavigationItem(
                        label = { Text(text = screen.label)},
                        selected = currentDestination?.hierarchy?.any{ it.route == screen.route } == true,
                        onClick = {
                            navController.navigate(screen.route)
                            {

                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true

                                restoreState = true
                            }
                        },
                        icon = {
                            Icon(painterResource(id = screen.icon), screen.label)
                        }, unselectedContentColor = Color.Gray
                    )
                }

            }
        }
    ){
        //Scaffold Content - How to access the compose function from the MainActivity NavGraph here?
     }
}
wqnecbli

wqnecbli1#

查看您的代码,我认为您需要在Dashboard函数的Scaffold内容中设置一个NavHost,以告诉系统您希望在布局中使用您创建的bottomBar切换可组合对象。
我看到您已经了解了嵌套导航,所以如果您只是想重用相同的NavHost,您可以尝试在特定的可组合函数中定义它。

@Composable
fun MyNavGraph(
    navController: NavHostController = rememberNavController(),
    userViewModel: FirebaseUserViewModel
){
    NavHost(navController = navController, startDestination = "auth"){
        navigation(startDestination = "logInUI", route = "auth"){
            composable("logInUI"){
                LogIn(
                    userViewModel,
                    onNavigate = {
                        navigateTo(it, navController)
                    }
                ).FinalView()
            }

            composable("signUpUI"){
                SignUpFragment(
                    userViewModel,
                    onNavigate = {
                        navigateTo(it, navController)
                    }
                ).FinalView()
            }
        }
        addDashBoardGraph(userViewModel, navController)
    }
}

我没有试过,所以让我知道是否适合你的情况。希望它能帮助一点。

a11xaf1n

a11xaf1n2#

你应该这样做-
在主活动中,调用MyBottomNavApp

class MainActivity : ComponentActivity() {
    lateinit var navController: NavController
    private val viewModel: MyAppViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window, false)
        installSplashScreen().apply {
            setKeepOnScreenCondition {
                viewModel.isLoading.value
            }
        }
        setContent {
            UnicornTheme {
                // Uncomment below and MyApp lines to use drawer navigation
                navController = rememberNavController()
                // MyApp(navController)
                // Uncomment MyBottomNavApp to get bottomnav navigation
                MyBottomNavApp(navController as NavHostController)
            }
        }
    }

    override fun onBackPressed() {
        super.onBackPressed()
    }
}

然后,使用NavHost实现MyBottomNavApp,如下所示

@Composable
fun MyBottomNavApp(
    navController: NavHostController
) {
    Scaffold(
        modifier = Modifier.navigationBarsPadding(),
        bottomBar = { MyBottomNavigation(navController = navController)},
    ) { innerPadding ->
        Box(Modifier.padding(innerPadding)) {
            NavHost(
                navController = navController,
                startDestination = Home.route
                ) {
                composable(Home.route) {
                    DashboardScreen(navController = navController)
                }

                composable(Settings.route) {
                    NavigationScreen(navController = navController)
                }
            }
        }
    }
}

然后,按如下方式实施目的地-

interface Destinations {
    val route: String
    val icon: ImageVector
    val title: String
}

object Home: Destinations {
    override val route = "Dashboard"
    override val icon = Icons.Filled.Dashboard
    override val title = "Dashboard"
}

object Settings: Destinations {
    override val route = "Navigation"
    override val icon = Icons.Filled.Navigation
    override val title = "Navigation"
}

然后,实现MyBottomNavigation如下-

@Composable
fun MyBottomNavigation(
    navController: NavController
) {
    val destinationList = listOf<Destinations> (
        Dashboard,
        Navigation
    )

    val selectedIndex = rememberSaveable {
        mutableStateOf(0)
    }

    BottomNavigation(
        backgroundColor = colorResource(id = R.color.primary_contrast),
        contentColor = colorResource(id = R.color.secondary_contrast)
    ) {
        destinationList.forEachIndexed{index, destination ->
            BottomNavigationItem(
                label = { Text(text = destination.title)},
                icon = { Icon(imageVector = destination.icon, contentDescription = destination.title)},
                selected = index == selectedIndex.value,
                onClick = {
                    selectedIndex.value = index
                    navController.navigate(destinationList[index].route) {
                        popUpTo(Home.route)
                        launchSingleTop = true
                    }
                }
            )
        }
    }
}

您可以在以下存储库的feature/develop_starter_kit_bottom_navigation分支中看到这方面的示例-
https://github.com/arunabhdas/unicorn-commerce/tree/feature/develop_starter_kit_bottom_navigation

相关问题