带有底部导航和Back Stack导航的Jetpack导航组件手柄导航控制器

如何解决带有底部导航和Back Stack导航的Jetpack导航组件手柄导航控制器

您好,我正在开发一个应用程序,但在“导航视图”中停留在导航上。

示例我有活动,并且在内部定义了如下所示的导航主机控制器

    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,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;

        }
    });

工作正常。但是现在我不得不处理我不懂的后退导航。

我的问题是假设我在底部导航中有4个菜单。主页,狩猎,Qbank,考试。

我被选为Qbank。 Qbank有5个片段A,B,C,D,E。现在我已经开始遍历片段A-> B B-> C C-> D

现在,我可以选择必须导航回Direct A like的位置。当前位置是D

D-> A

但是我如何回到A并清除我遍历A-> B-> C-> D的堆栈,我想清除此内容,就像我想从A重新开始。

我如何使用Jetpack导航组件。

我尝试了直接导航或弹出堆栈导航,但是它不起作用,这给了我一个错误,例如我直接导航到

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)

我不知道如何处理此导航。请帮助解决此问题

谢谢。

解决方法

您可以查看当前导航目的地,如果是起始目的地或所需目的地,则弹出包含内容的内容

public class MyLogger{
    private String message;

    // Getter
    // Setter
}

public class MyLoggerService(){
    @Autowired
    private MyLoggerRepo repo;

    public void save(String message){
        MyLogger log = new MyLogger();
        log.setMessage(message);
        repo.save(log);
    }
}
,

使用 popUpTo 从堆栈中删除前一个Fragment的实例,并使用 popUpToInclusive 删除 A Fragment 的第一个实例,否则您将有两个实例堆栈中的片段

Android官方文档中的演示代码:

导航图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"/>
,

您应为每个底部导航项使用不同的导航图。

这样,每个底部菜单项都将具有自己的图形以及各自的起始目标。因此,遵循此导航路径

A-> B B-> C C-> D并添加以下代码-

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

您可以弹出片段A,该片段将成为底部菜单项的起始目标,并且不会出现有关NavController目标的错误。

我尝试通过以下示例和代码进一步解释-

我们有三个菜单项,即仪表板,查找和选项,在主要活动中,我将使用以下代码来设置底部导航-

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 将是以下导航文件->

enter image description here

dashboard_navigation.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

<?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

<?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>

确保菜单项ID与导航图的ID相匹配。作为对Dashboard的检查,我已将菜单项ID用作android:id =“ @ + id / dashboard_navigation”,该ID与dashboard_navigation.xml图的相同ID

enter image description here

您还必须使用Google本身提供的Navigation Extension (In Kotlin)

要获取有关使用多个导航的更多信息,请单击here

如果您想了解如何在Java代码中使用Navigatin扩展文件,请检查我的答案here

快乐编码!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?