自定义 BottomNavigationView 的行为

Customize behavior of BottomNavigationView

提问人:Gleichmut 提问时间:11/18/2023 最后编辑:Gleichmut 更新时间:11/19/2023 访问量:26

问:

我想在单击其中的不同选项卡时弹出一个片段。BottomNavigationView

我有三个选项卡,其中第二个作为起始目的地。在第二个选项卡上,我可以搜索一些项目,后端的数据将显示在此堆栈中的另一个片段上,换句话说:BottomNavigationView

A - B - C (origin state)

    D
A - B - C (state after search has been performed)

在返回按钮单击时,此片段将被删除到原始状态,但如果在搜索用户单击另一个选项卡 A 或 C 后,堆栈将保留 D 片段,而 D 片段将在用户返回 B 选项卡后显示。 A - B - C

导航支持 in xml 选项,但默认导航不会在 xml 中定义导航操作 - 它支持开箱即用。至少我还没有找到如何覆盖这种行为。 我可能会听导航更改,但不清楚接下来如何进行。其他一些使用 fragmentManager.replace() 的解决方案看起来很丑陋。 看起来更好,但我还没有设法将其正确应用于这种情况,这也引起了对处理导航组件的正确方法的担忧。popUpInclusiveBottomNavigationViewOnItemViewSelectedListenernavigateUp()

实现这种行为的正确方法是什么?我希望当用户导航到其他选项卡时,从堆栈中弹出我的搜索片段。

<?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/mobile_navigation"
    app:startDestination="@+id/navigation_dashboard">

    <fragment
        android:id="@+id/navigation_home"
        android:name="ru.home.government.screens.deputies.DeputiesFragment"
        android:label="@string/title_deputies"
        tools:layout="@layout/fragment_deputies">
        <argument
            android:name="EXTRA_NO_BOTTOM_VIEW"
            app:argType="boolean"
            android:defaultValue="false" />

        <action
            android:id="@+id/action_navigation_home_to_navigation_dashboard"
            app:destination="@id/navigation_dashboard"
            app:popUpTo="@+id/navigation_home"
            app:popUpToInclusive="true" />

    </fragment>

    <fragment
        android:id="@+id/navigation_dashboard"
        android:name="ru.home.government.screens.laws.main.LawsMainFragment"
        android:label="@string/title_laws"
        tools:layout="@layout/fragment_laws" >

        <action
            android:id="@+id/action_navigation_dashboard_to_lawsFilteredFragment"
            app:destination="@id/navigation_laws_filtered"
            />
        <action
            android:id="@+id/action_navigation_dashboard_to_navigation_home"
            app:destination="@id/navigation_home"
            app:popUpTo="@+id/navigation_dashboard"
            app:popUpToInclusive="true"
            />
        <action
            android:id="@+id/action_navigation_dashboard_to_navigation_notifications"
            app:destination="@id/navigation_notifications"
            app:popUpTo="@+id/navigation_dashboard"
            app:popUpToInclusive="true"
            />

    </fragment>

    <fragment
        android:id="@+id/navigation_notifications"
        android:name="ru.home.government.screens.tracker.TrackerFragment"
        android:label="@string/title_tracker"
        tools:layout="@layout/fragment_tracker">

        <action
            android:id="@+id/action_navigation_notifications_to_navigation_dashboard"
            app:destination="@id/navigation_dashboard"
            app:popUpTo="@+id/navigation_home"
            app:popUpToInclusive="true" />

    </fragment>

    <fragment
        android:id="@+id/navigation_laws_filtered"
        android:name="ru.home.government.screens.laws.filter.LawsFilteredFragment"
        android:label="@string/title_search"
        tools:layout="@layout/fragment_law_filtered">

        <argument
            android:name="EXTRA_KEY"
            app:argType="string"
            android:defaultValue="false" />

        <action
            android:id="@+id/action_navigation_laws_filtered_to_navigation_home"
            app:destination="@id/navigation_home"
            app:popUpTo="@+id/navigation_dashboard"
            app:popUpToInclusive="true" />

        <action
            android:id="@+id/action_navigation_laws_filtered_to_navigation_notifications"
            app:destination="@id/navigation_notifications"
            app:popUpTo="@+id/navigation_dashboard"
            app:popUpToInclusive="true" />

    </fragment>
</navigation>
Android 导航 BottomNavigationView

评论

0赞 Rob 11/18/2023
你如何展示你的片段?如果您使用的是片段导航,则可以按照上面描述的 xml 方式进行设置,我假设您有一些处理 bottomNavView 项单击的代码,您可以在其中使用适当的片段导航操作
0赞 Gleichmut 11/18/2023
片段在 xml 文件中定义,但选项卡之间的导航由 自动处理。因此,您对 bottomNavView 项目单击的假设是不正确的,我什至没有看到覆盖它的方法。nav_graphBottomNavigationView
0赞 Gleichmut 11/18/2023
@Rob,我更新了帖子nav_graph.xml
1赞 Rob 11/19/2023
创建了一个类似的项目并测试了代码,答案是有效的 - 请检查@Gleichmut

答:

0赞 Rob 11/19/2023 #1

这对我有用,我创建了一个带有 4 个片段的测试项目,就像您的情况一样,只有其他东西可以背压,您也应该处理它,我将在最后提供该代码

<?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/mobile_navigation"
    app:startDestination="@+id/navigation_dashboard">

    <fragment
        android:id="@+id/navigation_home"
        android:name="ru.home.government.screens.deputies.DeputiesFragment"
        android:label="@string/title_deputies"
        tools:layout="@layout/fragment_deputies">
        <argument
            android:name="EXTRA_NO_BOTTOM_VIEW"
            app:argType="boolean"
            android:defaultValue="false" />

        <action
            android:id="@+id/action_navigation_home_to_navigation_dashboard"
            app:destination="@id/navigation_dashboard" />

    </fragment>

    <fragment
        android:id="@+id/navigation_dashboard"
        android:name="ru.home.government.screens.laws.main.LawsMainFragment"
        android:label="@string/title_laws"
        tools:layout="@layout/fragment_laws" >

        <action
            android:id="@+id/action_navigation_dashboard_to_lawsFilteredFragment"
            app:destination="@id/navigation_laws_filtered"
            />
        <action
            android:id="@+id/action_navigation_dashboard_to_navigation_home"
            app:destination="@id/navigation_home" />
        <action
            android:id="@+id/action_navigation_dashboard_to_navigation_notifications"
            app:destination="@id/navigation_notifications"
            app:popUpTo="@+id/navigation_dashboard"
            app:popUpToInclusive="true"
            />

    </fragment>

    <fragment
        android:id="@+id/navigation_notifications"
        android:name="ru.home.government.screens.tracker.TrackerFragment"
        android:label="@string/title_tracker"
        tools:layout="@layout/fragment_tracker">

        <action
            android:id="@+id/action_navigation_notifications_to_navigation_dashboard"
            app:destination="@id/navigation_dashboard"
            app:popUpTo="@+id/navigation_home"
            app:popUpToInclusive="true" />

    </fragment>

    <fragment
        android:id="@+id/navigation_laws_filtered"
        android:name="ru.home.government.screens.laws.filter.LawsFilteredFragment"
        android:label="@string/title_search"
        tools:layout="@layout/fragment_law_filtered">

        <argument
            android:name="EXTRA_KEY"
            app:argType="string"
            android:defaultValue="false" />

        <action
            android:id="@+id/action_navigation_laws_filtered_to_navigation_home"
            app:destination="@id/navigation_home" />

        <action
            android:id="@+id/action_navigation_laws_filtered_to_navigation_notifications"
            app:destination="@id/navigation_notifications" />

    </fragment>
</navigation>

注意*** 如果您想在后按时从通知导航到主页,请不要执行最后一部分,否则请执行以下步骤

和背压处理

定义 backPressedCallback

private val backPressedCallback = object : OnBackPressedCallback(enabled = true) {
    override fun handleOnBackPressed() {
        if (navController.currentDestination?.id == R.id.navigation_notifications) {
            navController.navigate(R.id.action_navigation_notifications_to_navigation_dashboard)
        }
    }
}

注册它

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val navView: BottomNavigationView = findViewById(R.id.bottom_nav_bar)

    navView.setupWithNavController(navController)
    navController.addOnDestinationChangedListener { _, destination, _ ->
        backPressedCallback.isEnabled = destination.id == R.id.navigation_notifications // enable back press custom handling only when notifications screen is on 
    }
    onBackPressedDispatcher.addCallback(this, backPressedCallback)
}

评论

0赞 Gleichmut 11/20/2023
谢谢!尽管它并不能完全解决问题: a. 切换到选项卡时,片段仍位于 .b. 突出显示了错误的选项卡。你介意考虑更容易根据我的代码库检查代码并 github.com/Gelassen/government-rus 分支进行拉取请求CDBbugfix/navigation-in-search