如何使用底部导航视图和 Android 导航组件将参数传递给片段?

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

是否可以使用底部导航视图和导航组件传递和访问片段中的参数?

我正在使用一种具有许多片段方法的活动,其中我的顶级片段需要一个参数(通常通过 newInstance 生成的方法完成)。我查看了导航组件开发人员指南和代码实验室,但它只提到使用 safeargs 并在目的地和操作中添加参数标签。

这是我的导航图:

<navigation xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" 
    app:startDestination="@id/homeFragment">

    <fragment android:id="@+id/homeFragment"
          android:name="uk.co.homeready.homeready.HomeFragment"
          android:label="fragment_home"
          tools:layout="@layout/fragment_home">
          <!--Do I create an argument block here?-->
    </fragment>

    <fragment android:id="@+id/calculatorFragment"
          android:name="uk.co.homeready.homeready.CalculatorFragment"
          android:label="fragment_calculator"
          tools:layout="@layout/fragment_calculator"/>

    <fragment android:id="@+id/resourcesFragment"
          android:name="uk.co.homeready.homeready.ResourcesFragment"
          android:label="fragment_resources"
          tools:layout="@layout/fragment_resources"/>

</navigation>

底部导航视图菜单:

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/homeFragment"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/title_home"/>

    <item
        android:id="@+id/calculatorFragment"
        android:icon="@drawable/ic_baseline_attach_money_24px"
        android:title="@string/title_calculator"/>

    <item
        android:id="@+id/resourcesFragment"
        android:icon="@drawable/ic_baseline_library_books_24px"
        android:title="@string/title_resources"/>

</menu>

主要活动:

override fun onCreate(savedInstanceState: Bundle?) {
        ...
        val navController = Navigation.findNavController(this, 
        R.id.nav_host_fragment)
        bottom_navigation.setupWithNavController(navController)
        ....
}

activity_main.xml

<android.support.constraint.ConstraintLayout>
    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph"/>

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        app:menu="@menu/bottom_navigation"/>

</android.support.constraint.ConstraintLayout>

首页片段

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val argument = //TODO access argument here
    ...
}
android android-fragments bottomnavigationview android-jetpack android-architecture-navigation
4个回答
31
投票

如果我理解正确,您希望将参数传递到与菜单项绑定的目的地。尝试在活动 onCreate 方法中使用“OnDestinationChangedListener”,如下所示:

navController.addOnDestinationChangedListener { controller, destination, arguments ->
        when(destination.id) {
            R.id.homeFragment -> {
                val argument = NavArgument.Builder().setDefaultValue(6).build()
                destination.addArgument("Argument", argument)
            }
        }
    }

更新:

如果您希望起始目的地接收默认参数,则实现应该有所不同。 首先,从“NavHostFragment”xml 标记中删除“app:navGraph="@navigation/nav_graph"”。

然后,在 onCreate 活动中,您需要膨胀图表:

 val navInflater = navController.navInflater
 val graph = navInflater.inflate(R.navigation.nav_graph)

然后将您的参数添加到图表中(此参数将附加到起始目的地)

val navArgument1=NavArgument.Builder().setDefaultValue(1).build()           
val navArgument2=NavArgument.Builder().setDefaultValue("Hello").build()
graph.addArgument("Key1",navArgument1)
graph.addArgument("Key2",navArgument2)

然后将图形附加到 NavController:

navController.graph=graph

现在您的第一个目的地应该收到附加的参数。


7
投票

正确的方法确实是在目的地上设置

<argument>
块。

<fragment android:id="@+id/homeFragment"
      android:name="uk.co.homeready.homeready.HomeFragment"
      android:label="fragment_home"
      tools:layout="@layout/fragment_home">
      <argument
          android:name="Argument"
          android:defaultValue="value"
          />
</fragment>

这将自动使用默认值填充片段的参数,而不需要任何额外的代码。从 Navigation 1.0.0-alpha09 开始,无论您是否使用 Safe Args Gradle 插件,都是如此。


3
投票

默认值对我来说不可用,因为我有动态菜单项,这些菜单项可能具有多个具有不同参数的相同目的地。 (从服务器更改)

实现BottomNavigationView.OnNavigationItemSelectedListener:

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    val fragmentId = item.itemId
    val arguments = argumentsByFragmentId[fragmentId] // custom mutableMapOf<Int, Bundle?>() with arguments
    navController().navigate(fragmentId, arguments)
    return true
}

要使用它,您将通过替换侦听器来接管导航。这里的调用顺序很重要:

bottomNavigationView.setupWithNavController(navController)
bottomNavigationView.setOnNavigationItemSelectedListener(this)

0
投票

我的参数已经在导航图 xml 中定义,不知道为什么,但@Alex 的答案对我不起作用,而是我这样做了(来自destinationChangedListener):

 arguments?.putParcelable("argname", argvalue)

注意,当深度链接到特定的导航栏选项卡时,我使用它来给出特定的响应。默认情况下,我也需要这样做(以避免重复使用同一个包并再次发生深层链接处理):

arguments?.remove("argname")
© www.soinside.com 2019 - 2024. All rights reserved.