通过使用BottomNavigation和Navigation组件在选项卡之间传递数据

5

使用具有多个导航图和类似于Google导航示例的BottomNavigationView的导航组件时,我遇到了这样的问题。

我无法以编程方式从底部导航中的一个选项卡导航到另一个选项卡并传递参数。例如,我有三个导航图和三个底部导航选项卡(每个选项卡一个图)。

我需要以编程方式从一个选项卡导航到另一个选项卡,以便“另一个”选项卡可以获得来自第一个选项卡的传递参数。


我认为这个问题已经在这里得到了回答: https://stackoverflow.com/questions/41760893/how-to-pass-data-between-tabs - UnBanned
2个回答

0

如果您需要将大量数据从一个选项卡移动到另一个选项卡,那么您可能需要一个本地数据库。此外,您可以使用Intents传递它们。但是,如果您不知道如何实现底部导航栏或选项卡,则建议您查看以下内容:

https://medium.com/@suragch/how-to-add-a-bottom-navigation-bar-in-android-958ed728ef6c

https://androidwave.com/bottom-navigation-bar-android-example/

https://medium.com/@droidbyme/android-material-design-tabs-tab-layout-with-swipe-884085ae80ff


0

我成功地创建了一个解决方法,基于androidx.navigation.ui.NavigationUI的内部实现。

引入以下接口:

/**
 * Use this interface to navigate between bottom tabs instead of findNavController().navigate().
 *
 * Using navController's navigation can lead to incorrect app states, because each tab
 * holds its own backstack. If for example you want to open tab2 from tab1
 * by clicking button on tab1 fragment, tab2 fragment will be added to tab1 backstack.
 * In the same time tab2 will get highlighted, so clicking on tab1 to navigate back to tab1 backstack
 * will have no action, since you are already on tab1.
 *
 */
interface BottomTabNavigator {
    fun openTab(@IdRes tabId: Int, args: Bundle? = null)
}

在设置导航栏的位置(通常是MainActivity)提供以下实现:

override fun openTab(@IdRes tabId: Int, args: Bundle?) {
    val navController = (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController // obtain nav controller. This code may differ depending on the place in which you are implementing this interface
    val menuItem = binding.bottomNav.menu.findItem(tabId) // find menu item associated with tabId, this can also slightly differ depending on how you access bottomNav
    openTab(
       menuItem = menuItem,
       navController = navController,
       args = args,
       restoreState = restoreState
    )
}

/**
* Implementation is based on [NavigationUI.onNavDestinationSelected].
* It works similarly, but additionally allows for passing args.
*/
private fun openTab(menuItem: MenuItem, navController: NavController, args: Bundle?, restoreState: Boolean): Boolean {
    val builder = NavOptions.Builder().setLaunchSingleTop(true).setRestoreState(true) // you can also add restoreState to openTab in BottomTabNavigator if you need to set it from outside

    if (menuItem.order and Menu.CATEGORY_SECONDARY == 0) {
        builder.setPopUpTo(
            destinationId = navController.graph.findStartDestination().id,
            inclusive = false,
            saveState = true
        )
    }
    return try {
       navController.navigate(
           resId = menuItem.itemId,
           args = args,
           navOptions = builder.build()
       )

       navController.currentDestination?.matchDestination(item.itemId) == true
    } catch (e: IllegalArgumentException) {
        false
    }
}

// matchDestination is internal in NavigationUI.onNavDestinationSelected, we have to port it as well.
fun NavDestination.matchDestination(@IdRes destId: Int): Boolean =
        hierarchy.any { it.id == destId }

你可以在Fragment中使用它,例如:

val bottomTabNavigator = requireActivity() as BottomTabNavigator
bottomTabNavigator.openTab(R.id.myTabId, bundleOf("myKey", "myValue")

我真的希望我们可以只使用navController.navigate(),但是当我尝试导航到与我的选项卡相关联的目标时(如docs中所述),会出现问题。从选项卡1导航到选项卡2可以正常工作,但是当按下选项卡1以返回它时,仍然停留在选项卡2上。
你甚至可以在nav sample中看到它:
Title.kt中替换
view.findViewById<Button>(R.id.about_btn).setOnClickListener {
    findNavController().navigate(R.id.action_title_to_about)
}

使用

view.findViewById<Button>(R.id.about_btn).setOnClickListener {
    findNavController().navigate(
        resId = R.id.list,
        args = null, // note that I don't pass args here, but it is to show case different issue
        navOptions = NavOptions.Builder().setPopUpTo(R.id.list, false).build()
    )
}

运行应用程序并执行以下操作:

  • 应用程序将在主页选项卡上打开
  • 点击关于按钮
  • 它将带您到排行榜选项卡
  • 点击主页选项卡
  • 它将突出显示主页选项卡,但您仍将停留在排行榜片段中

Broken bottom bar behaviour - Home is highlighted, but Leaderboard is opened


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接