简体   繁体   English

Jetpack 导航组件处理带有底部导航的导航控制器及其返回堆栈导航

[英]Jetpack Navigation Component handle navigation controller with Bottom Navigation and it's Back Stack navigation

Hello i am developing one application and i am stuck on navigation in Navigation View.您好,我正在开发一个应用程序,但我一直停留在导航视图中的导航上。

Example I have activity and inside i have define navigation host controller like below示例我有活动,在里面我定义了导航主机控制器,如下所示

    setSupportActionBar(mMainToolbar);

    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.homeFragment, R.id.questionBankFragment,
            R.id.testFragment, R.id.dailyHuntFragment,
            R.id.liveClassesFragment)
            .setOpenableLayout(mMainDrawerLayout)
            .build();

    View mNavigationViewHeaderView = mNavigationView.getHeaderView(0);

    mNavHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
    mNavController = Navigation.findNavController(this, R.id.nav_host_fragment);

    NavigationUI.setupActionBarWithNavController(this, mNavController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(mNavigationView, mNavController);

    NavigationUI.setupWithNavController(mMainToolbar, mNavController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(mBottomNavigationView, mNavController);

    mNavController.addOnDestinationChangedListener((controller, destination, arguments) -> {
        switch (destination.getId()) {

            case R.id.homeFragment:
            case R.id.questionBankFragment:
                mMainToolbar.setVisibility(View.VISIBLE);
                mBottomNavigationView.setVisibility(View.VISIBLE);
                setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
                setDrawerLocked(false);
                break;


            case R.id.welcomeFragment:
            case R.id.loginFragment:
                mMainToolbar.setVisibility(View.GONE);
                mBottomNavigationView.setVisibility(View.GONE);
                setStatusBarColor(Color.WHITE);
                setDrawerLocked(true);
                break;

        
            case R.id.customModuleFragment:
            case R.id.createCustomModuleOneFragment:
            case R.id.createCustomModuleTwoFragment:
                mBottomNavigationView.setVisibility(View.GONE);
                setDrawerLocked(true);
                break;
            case R.id.logoutFragment:

                new AppSharedPreference(MainActivity.this).clearAllData();

                Intent intent = new Intent(getApplicationContext(), UserAuthanticationActivity.class);
                startActivity(intent);
                finish();
                break;

        }
    });

It is working fine.它工作正常。 but now i have to handle navigation on back stack that i not able to understand.但现在我必须处理我无法理解的后堆栈导航。

My Question is suppose i am bottom navigation There are 4 Menu.我的问题是假设我是底部导航有 4 个菜单。 Home, Hunting , Qbank, Exam.家,狩猎,Qbank,考试。

I am selected Qbank.我被选为Qbank。 Qbank have 5 fragments A, B, C, D, E. now i have started traverse Fragment A -> BB -> CC -> D Qbank 有 5 个片段 A、B、C、D、E。现在我已经开始遍历片段 A -> BB -> CC -> D

and now i have choice where i have to navigate Back to Direct A like .现在我可以选择在哪里导航回到直接 A 喜欢。 Current position is D当前位置是 D

D - > A D - > A

but how i can get back to A and clear stack that i traverse A -> B -> C -> D i want clear this and it's like i want to start again with A.但是我如何回到 A 并清除我遍历的堆栈 A -> B -> C -> D 我想清除这个,就像我想从 A 重新开始一样。

How I can make possible with Jetpack Navigation Component.我如何使用 Jetpack 导航组件实现这一目标。

i tried direct navigation or popback stack navigation but it is not work it is gives me error like if i directly navigato to我尝试了直接导航或弹出堆栈导航,但它不起作用它给了我错误,就像我直接导航到

java.lang.IllegalStateException: View androidx.core.widget.NestedScrollView{98060fe VFED..... ......ID 0,0-0,0} does not have a NavController set
        at androidx.navigation.Navigation.findNavController(Navigation.java:84)
        at app.technotech.koncpt.McqTestFragment$2.onClick(McqTestFragment.java:232)
        at android.view.View.performClick(View.java:7201)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
        at android.view.View.performClickInternal(View.java:7170)
        at android.view.View.access$3500(View.java:806)
        at android.view.View$PerformClick.run(View.java:27562)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

I don't have any idea how i can handle this navigation.Pleas help to fix this my solution我不知道如何处理这个导航。请帮助解决这个我的解决方案

Thanks in advance.提前致谢。

You can check the current navigation destination and pop inclusive if that's your start or desired destination如果这是您的起点或想要的目的地,您可以检查当前导航目的地并弹出包容性

    if (navController.currentDestination.id == navController.graph.YOUR_PREFERED_DESTIONATION) {
    
            navController.popBackStack(
                navController.graph.YOUR_PREFERED_DESTIONATION, true
            )
    }else {
   navController.navigate(R.id.other_destination)
}

Use popUpTo to remove instances of previous Fragment from backstack and use popUpToInclusive to remove first instance of A Fragment otherwise you will have two instances of A Fragment in your stack:使用popUpTo从 backstack 中删除先前 Fragment 的实例,并使用popUpToInclusive删除A Fragment 的第一个实例,否则您的堆栈中将有两个A Fragment实例:

A demo code from Android official documention:来自Android官方文档的演示代码:

Navigation Graph XML View:导航图 XML 视图:

<fragment
android:id="@+id/c"
android:name="com.example.myapplication.C"
android:label="fragment_c"
tools:layout="@layout/fragment_c">

<action
    android:id="@+id/action_d_to_a"
    app:destination="@id/a"
    app:popUpTo="@+id/a"
    app:popUpToInclusive="true"/>

You should use different navigation graph for each bottom navigation item.您应该为每个底部导航项使用不同的导航图。

So that each bottom menu item would have its own graph with their own starting destinations.这样每个底部菜单项都有自己的图表和自己的起始目的地。 So following this navigation path所以按照这个导航路径

A -> BB -> CC -> D and adding following code- A -> BB -> CC -> D 并添加以下代码-

<action
    android:id="@+id/action_d_to_a"
    app:destination="@id/a"
    app:popUpTo="@+id/a"
    app:popUpToInclusive="true"/>

you can pop up to fragment A which will be a starting destination of bottom menu item and you will not get error about NavController destination.您可以弹出片段 A,这将是底部菜单项的起始目的地,并且您不会收到有关 NavController 目的地的错误。

I try to explain further with following example and code-我尝试用以下示例和代码进一步解释-

We have three menu item ie Dashboard, Find and options, in main activity I will use following code to setup bottom navigation-我们有三个菜单项,即仪表板、查找和选项,在主要活动中,我将使用以下代码来设置底部导航-

private void setupBottomNavigation() {
        BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_nav_view);
        bottomNavigationView.setItemIconTintList(null);

        List<Integer> navGraphList = new ArrayList<>();
        navGraphList.add(R.navigation.dashboard_navigation);
        navGraphList.add(R.navigation.find_navigation);
        navGraphList.add(R.navigation.options_navigation);

        LiveData<NavController> navControllerLiveData = new NavigationExtensions().setupWithNavController(
                bottomNavigationView
                , navGraphList
                , getSupportFragmentManager()
                , R.id.fragment_container, getIntent()
        );
        currentNavController = navControllerLiveData;
    }

R.navigation.dashboard_navigation , R.navigation.find_navigation & R.navigation.options_navigation will be navigation files as following- R.navigation.dashboard_navigationR.navigation.find_navigationR.navigation.options_navigation将导航文件如下-

在此处输入图片说明

dashboard_navigation.xml仪表板_导航.xml

<?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/dashboard_navigation"
    app:startDestination="@id/dashboardFragment">

    <fragment
        android:id="@+id/dashboardFragment"
        android:name="your.package.DashboardFragment"
        android:label=""
        tools:layout="@layout/fragment_dashboard" >

    </fragment>

    <fragment
        //add other fragment to this graph

    </fragment>

<navigation>

activity_main.xml活动_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/coordinatorLayout_main"
    android:background="?android:attr/colorBackground"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="?attr/actionBarSize" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        app:itemTextColor="@drawable/bottom_nav_selector"
        android:id="@+id/bottom_nav_view"
        android:layout_width="match_parent"
        app:itemRippleColor="?colorPrimary"
        app:labelVisibilityMode="labeled"
        android:layout_height="?attr/actionBarSize"
        android:layout_gravity="bottom"
        app:menu="@menu/bottom_nav_menu"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

bottom_nav_menu.xml bottom_nav_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/dashboard_navigation"
        android:icon="@drawable/dashboard_icon_selector"
        android:title="@string/dashboardTitle" />

    <item
        android:id="@+id/find_navigation"
        android:icon="@drawable/find_icon_selector"
        android:title="@string/findTitle" />

    <item
        android:id="@+id/options_navigation"
        android:icon="@drawable/setting_icon_selector"
        android:title="@string/optionTitle" />

</menu>

Make sure menu item id match with id of navigation graph.确保菜单项 id 与导航图的 id 匹配。 As check for Dashboard, I have used menu item id as android:id="@+id/dashboard_navigation" which is the same id, for dashboard_navigation.xml graph作为检查仪表板,我使用菜单项 id 作为 android:id="@+id/dashboard_navigation" 这是相同的 id,用于dashboard_navigation.xml 图形

在此处输入图片说明

You must be also using Navigation Extension (In Kotlin) provided by google itself.您还必须使用谷歌本身提供的导航扩展(在 Kotlin 中)

To get more information on using multiple nav-graghs, click here要获取有关使用多个导航图的更多信息,请单击此处

If you want to understand how to use Navigatin Extension File with your java code, please check my answer here .如果您想了解如何在 Java 代码中使用 Navigatin 扩展文件,请在此处查看我的回答。

Happy Coding !快乐编码!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 带有底部导航视图和导航组件的后退导航 - Back navigation with bottom navigation view and navigation component 喷气背包导航-&gt; 清除后退堆栈后,底部导航的多个后退堆栈不起作用 - jetpack navigation -> multiple back stack with bottom navigation not working when back stack is cleared 带底部导航的导航组件 - Navigation component with bottom navigation 后退堆栈在 Jetpack Navigation 中无法正常工作 - Back stack not working properly in Jetpack Navigation Android Jetpack Navigation 使用 BottomNavigationView 正确返回堆栈 - Android Jetpack Navigation proper back stack with BottomNavigationView 导航组件 NavDeepLinkBuilder 回栈 - Navigation Component NavDeepLinkBuilder back stack Android导航组件回栈 - Android navigation component back stack 如何使用 Jetpack Compose + Navigation(无片段)处理后退导航 - How to handle back navigation with Jetpack Compose + Navigation (without fragments) 如何使用 Android Jetpack 的导航组件禁用后退导航并删除 Fragment 上的后退箭头? - How do I disable back navigation and remove the back arrow on a Fragment, using Android Jetpack's Navigation component? Espresso pressBack() 检查后退导航是否适用于 Jetpack 导航组件 - Espresso pressBack() to check if back navigation works with Jetpack Navigation Component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM