【问题标题】:Passing arguments in BottomNavigationView with navigation Component使用导航组件在 BottomNavigationView 中传递参数
【发布时间】:2018-12-30 00:15:39
【问题描述】:

我目前正在使用新的(对我而言)导航组件编写应用程序。我已经用一个导航图来导航我的应用程序的基础知识,我有一个带有 BottomNavigationView 的片段,其中有 3 个单独的片段,我已经设法更新它以使用导航组件(至于我的问题)使用具有与导航项匹配的 ID 的菜单。我以前使用 newInstance 方法将包传递给 onCreate 的片段现在显然没有使用,但我仍然需要将包传递给我的片段。

我找不到任何这样做的例子,因为片段是隐式创建的。

我的代码结构为 ClientFragment,它是导航抽屉等的宿主片段;

class ClientFragment : Fragment() {

    private val viewModel: ClientViewModel by viewModel()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_client, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

       viewModel.client = arguments?.getParcelable(ARG_CLIENT)!!

        toolbar_client.title = viewModel.client.name
        toolbar_client.setNavigationOnClickListener { Navigation.findNavController(view).navigateUp() }
    }
}

这个类以前在我的片段的 onclick 监听器上持有,带有一个 newInstance 方法,其中工具 viewModel.client。

我在 nav_graph 中的片段都是相似的。第一个片段;

class ClientDetailsFragment : Fragment() {

    private val viewModel: ClientViewModel by viewModel()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_client_details, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

       // viewModel.client = arguments?.getParcelable(ARG_CLIENT)!!

        initClientDetails()
    }

    private fun initClientDetails() {
//        text_client_details_name.text = viewModel.client.name
//        text_client_details_account_number.text = viewModel.client.accountNumber
//        text_client_details_mobile_number.text = viewModel.client.mobileNumber
//        text_client_details_landline_number.text = viewModel.client.landlineNumber
//        text_client_details_email.text = viewModel.client.email
//        text_client_details_address.text = "NOT YET IMPLEMENTED"
//
//        text_client_description_body.text = viewModel.client.description
//        text_client_system_details_body.text = viewModel.client.systemDetails
    }
}

应用程序在注释掉的行崩溃;

// viewModel.client = arguments?.getParcelable(ARG_CLIENT)!! 

我的导航图和菜单是;

导航图;

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/client_nav_graph"
    app:startDestination="@id/clientDetailsFragment">

    <fragment
        android:id="@+id/clientCustomersFragment"
        android:name="com.management.engineering.alarm.alarmengineermanagement.features.client.ClientCustomersFragment"
        android:label="ClientCustomersFragment"
        tools:layout="@layout/fragment_client_customers" />

    <fragment
        android:id="@+id/clientDetailsFragment"
        android:name="com.management.engineering.alarm.alarmengineermanagement.features.client.ClientDetailsFragment"
        android:label="ClientDetailsFragment"
        tools:layout="@layout/fragment_client_details"/>

    <fragment
        android:id="@+id/clientJobHistoryFragment"
        android:name="com.management.engineering.alarm.alarmengineermanagement.features.client.ClientJobHistoryFragment"
        android:label="ClientJobHistoryFragment"
        tools:layout="@layout/fragment_client_job_history" />

</navigation>

菜单;

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/clientDetailsFragment"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="Details"/>
    <item
        android:id="@+id/clientJobHistoryFragment"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="Job History"/>
    <item
        android:id="@+id/clientCustomersFragment"
        android:icon="@drawable/ic_launcher_foreground"
        android:title="Customers"/>
</menu>

我发现您可以向导航图添加参数,但没有找到关于在此特定场景中放置它们的位置,我还知道在使用 .navigate 导航时可以手动添加包。

我有没有办法在我的 ClientFragment 中设置每个片段的参数

viewModel.client

更新:

我的论点问题通过使用在 BottomNavigationView 中的所有片段之间共享的视图模型得到解决(我在向朋友输入问题时意识到这一点)和导航本身我将它添加到 ClientFragment;

bottom_nav_client.setupWithNavController(
            Navigation.findNavController(
                    view.findViewById<View>(R.id.fl_client_nav_container)
            )
    )

以及我的片段客户端的 xml;

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar_client"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navigationIcon="?attr/NavigationBackIconLight"
        app:titleTextColor="@color/white" />

    <fragment
        android:id="@+id/fl_client_nav_container"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/bottom_nav_client"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolbar_client"
        app:navGraph="@navigation/client_nav_graph" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_client"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="?android:attr/windowBackground"
        app:itemBackground="@color/colorPrimary"
        app:itemIconTint="@drawable/bottom_nav_color"
        app:itemTextColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/client_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

这与如上所示相同的导航图和菜单相结合。

【问题讨论】:

  • 你是怎么做到的?
  • @jL4 我用答案更新了我的问题。

标签: kotlin androidx


【解决方案1】:

接受的答案中提到的 Codelabs 没有提到将参数传递给 BottomNavigationView 中的片段。

用自定义设置覆盖由 setupWithNavController() 设置的 OnNavigationItemSelectedListener:

val args = Bundle()

bottomNavigationView.setupWithNavController(navController)
bottomNavigationView.setOnNavigationItemSelectedListener { item ->
    navController.navigate(item.itemId, args)
    true
}

【讨论】:

    【解决方案2】:

    导航架构组件 documentation 展示了如何定义目标参数,在您的具体情况下,您应该创建一个自定义Parcelable 类(即Client)并将其作为参数包含在对应的片段。

    <fragment
        android:id="@+id/clientCustomersFragment"
        android:name="com.management.engineering.alarm.alarmengineermanagement.features.client.ClientCustomersFragment"
        android:label="ClientCustomersFragment"
        tools:layout="@layout/fragment_client_customers" >
    
        <action
            android:id="@+id/client_to_details"
            app:destination="@+id/clientDetailsFragment" />
    
    </fragment>
    
    <fragment
        android:id="@+id/clientDetailsFragment"
        android:name="com.management.engineering.alarm.alarmengineermanagement.features.client.ClientDetailsFragment"
        android:label="ClientDetailsFragment"
        tools:layout="@layout/fragment_client_details">
    
        <argument
            android:name="client"
            app:argType="com.management.engineering.alarm.alarmengineermanagement.features.client.Client" />
    
    </fragment>
    

    'androidx.navigation.safeargs' gradle 插件将生成ClientToDetails 和ClientDetailsFragmentArgs 类,可用于传递。检索参数client。

    来源

    val client: Client = TODO()
    val navController: NavController = TODO()
    navController.navigate(ClientToDetails(client))
    

    目的地

    val client =  ClientDetailsFragmentArgs.fromBundle(arguments).client
    

    【讨论】:

    • 当用户指出将其连接到 BottomNav 或 DrawerLayout 时,我们不会手动调用 navigate,而是通过将 NavController 连接到相关菜单来调用它。所以这行不通。
    【解决方案3】:

    【讨论】:

    • 在“9. 使用菜单、抽屉和底部导航进行导航”中,我没有看到任何提及为底部导航菜单中的目标设置参数值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多