为什么导航在版本 2.4.1 的导航抽屉活动模板中不起作用?

2023-12-20

(使用Android Studio 2021.1.1)

使用导航抽屉活动创建一个新项目:

  1. 使用导航抽屉活动模板创建了一个默认的 Android 应用程序。
  2. 在项目中添加了一个设置片段来测试action_settings菜单和配置菜单项。
  3. 被覆盖onOptionsItemSelected() in MainActivity.java像这样处理设置菜单:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Bundle bundle = new Bundle();
        switch (item.getItemId()) {
            case R.id.action_settings:
                Navigation
                    .findNavController(this, R.id.nav_host_fragment_content_main)
                    .navigate(R.id.nav_settings);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

Testing:

运行项目,抽屉菜单工作正常并按预期打开片段。问题是,当您单击溢出菜单打开设置片段时,它可以工作,但打开主页片段时,抽屉菜单不再工作。

观察:

经过一些测试,我发现这是因为依赖版本的原因,将其从2.4.1降级到2.3.5可以解决问题。

我的代码有问题还是因为 API 更改?如何在不降级的情况下处理这个问题?

额外信息:

In MainActivity's onCreate()方法我添加了以下内容:

     mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow, R.id.nav_settings)
                .setOpenableLayout(drawer)
                .build();

app模块的build.gradle:

plugins {
    id 'com.android.application'
}

android {
    compileSdk 31

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 23
        targetSdk 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 
            'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    buildFeatures {
        viewBinding true
    }

    buildToolsVersion '32.0.0'
        ndkVersion '23.1.7779620'
    }

    dependencies {
        implementation 'androidx.appcompat:appcompat:1.4.1'
        implementation 'com.google.android.material:material:1.5.0'
        implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
        implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
        implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
        implementation 'androidx.navigation:navigation-fragment:2.4.1'
        implementation 'androidx.navigation:navigation-ui:2.4.1'
        implementation 'androidx.legacy:legacy-support-v4:1.0.0'
        
        testImplementation 'junit:junit:4.13.2'
        androidTestImplementation 'androidx.test.ext:junit:1.1.3'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    }
}

tl/dr:您应该遵循将目的地与菜单项文档联系起来 https://developer.android.com/guide/navigation/navigation-ui#Tie-navdrawer并使用NavigationUI.onNavDestinationSelected()获得正确的行为:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    NavController navController = Navigation.findNavController(this,
        R.id.nav_host_fragment_content_main);

    // By calling onNavDestinationSelected(), you always get the right behavior
    return NavigationUI.onNavDestinationSelected(item, navController)
            || super.onOptionsItemSelected(item);
}

Why

导航2.4用途多个后退堆栈 https://medium.com/androiddevelopers/navigation-multiple-back-stacks-6c67ba41952f与你的每个元素相关联NavigationView根据添加抽屉式导航指南 https://developer.android.com/guide/navigation/navigation-ui#add_a_navigation_drawer:

开始于导航2.4.0-alpha01 https://developer.android.com/jetpack/androidx/releases/navigation#2.4.0-alpha01,当您使用 setupWithNavController 时,每个菜单项的状态都会被保存和恢复。

这意味着“主”屏幕有一个与之关联的后堆栈,当您点击该图标时,该后堆栈会恢复,画廊、幻灯片和设置也是如此。这就是该项目的状态保存方式。

这意味着每次点击抽屉中的项目不仅会导航到该屏幕,还会交换与该项目关联的整个后堆栈 - 您从第一个屏幕导航到的所有内容。

所以当你打电话时Navigation.findNavController(this, R.id.nav_host_fragment_content_main).navigate(R.id.nav_settings);,您所做的事情与选择抽屉中的“设置”项目不同 - 您只是将“设置”屏幕添加到“主”屏幕的后堆栈中。这就是为什么点击“主页”图标不会执行任何操作 - 您已经位于“主”屏幕的后堆栈上。

您真正想要做的是交换到与 nav_settings 项关联的完全独立的返回堆栈。这会将 nav_settings 返回堆栈与主页返回堆栈分开,从而确保点击主页图标可返回主屏幕的返回堆栈。

这正是NavigationUI.onNavDestinationSelected() https://developer.android.com/reference/androidx/navigation/ui/NavigationUI#onNavDestinationSelected(android.view.MenuItem,androidx.navigation.NavController)API 所做的(因为这正是setupWithNavControllerAPI 使用),因此您可以直接在您的onOptionsItemSelected().

但是,如果您想手动调用navigate()(顺便说一句,这意味着您没有获得使用时默认获得的交叉淡入淡出动画onNavDestinationSelected),您可以添加保存状态标志 https://developer.android.com/guide/navigation/navigation-navigate#savestate到您的导航呼叫以编程方式应用 NavOptions https://developer.android.com/guide/navigation/navigation-navigate#programmatic:

@Override
 public boolean onOptionsItemSelected(MenuItem item) {
    Bundle bundle =new Bundle();
    switch (item.getItemId()) {
        case R.id.action_settings:
        {
            // Manually build the NavOptions that manually do
            // what NavigationUI.onNavDestinationSelected does for you
            NavOptions navOptions = new NavOptions.Builder()
                .setPopUpTo(R.id.nav_home, false, true)
                .setRestoreState(true)
                .build();

            NavController navController = Navigation.findNavController(this, 
                R.id.nav_host_fragment_content_main);

            navController.navigate(R.id.nav_settings, navOptions);
            return true;
        }

        default:
            return super.onOptionsItemSelected(item);
    }
}

请注意,setupWithNavControllerAPI 依赖于嵌套图 https://developer.android.com/guide/navigation/navigation-nested-graphs当前目的地的信息来确定选择哪个项目 - 期望“主页”选项卡中的所有目的地都是“主页”导航图的一部分。因为你已经切换到 nav_settings,setupWithNavController假设您已交换到该后堆栈。由于您实际上还没有这样做,这就是为什么您选择的项目与您所在的后堆栈不同步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么导航在版本 2.4.1 的导航抽屉活动模板中不起作用? 的相关文章

随机推荐

  • Python。 while 循环中的变量未更新。

    我对编程非常陌生 我在编写一个基本的猜谜游戏时遇到了问题 x是计算机生成的随机数 该程序应该比较 previous guess x 的绝对值和新猜测减去 x 并告诉用户他们的新猜测是否更近或更远 但变量 previous guess 并未使
  • 随机数生成器,如何获得不相同的随机数

    我正在制作一个随机数生成器 但我不想再次生成这些数字 例如 1 2 3 4 是完美的 1 1 2 4 不是我想要的 因为数字重复出现 我看过这里 没有人能回答我正在寻找的问题 按照我的逻辑 这应该可行 但我不知道我做错了什么 我是 pyth
  • 如何在 Excel 工作表内的表对象中插入行?

    我在尝试将行插入现有表对象时遇到困难 这是我的代码片段 string connectionString Provider Microsoft ACE OLEDB 12 0 Data Source C myExcelFile xlsx Ext
  • Jmeter HTTPS代理配置

    我正在尝试使用 jmeter 加载测试 https 网站 我已经使用 jmeter bin 中 proxyserver jks 文件中的 keytool 安装了客户端证书 pfx 我还使用jmeter手册配置了jmeter代理和firefo
  • 如何将 Bamboo 变量从 Bamboo 脚本发送到 docker 容器?

    我正在为bamboo 使用 Docker 插件 我需要在 docker 容器中执行一个脚本 sh 脚本包含 echo ini source path bamboo ini source path 如果我将此行直接放入容器命令中 则 bamb
  • 删除或重置 Cookie

    我正在设置一个cookieRequest Cookies TemplateName value在我的申请的其中一页 第 3 页 上 现在我可以从第 3 页导航到第 4 页和第 2 页 并保留 cookie 的值 但是现在当我注销并再次登录时
  • RxJS 更新,类型“typeof Observable”上不存在属性“merge”

    我更新了我的材质角度项目 以在表中包含可扩展的详细信息行 为此 我需要升级到 rsjx 6 现在我收到以下错误 我对角度完全陌生 所以不幸的是我不知道如何解决这个问题 Property merge does not exist on typ
  • 发送带有授权标头的 axios get 请求

    我尝试使用 vue js 发送 axios get 请求 当不需要发送标头时它工作得很好 但是 当需要发送授权 jwt 时 我收到 CORS 错误 对预检请求的响应未通过访问控制检查 请求的资源上不存在 Access Control All
  • 通过地理位置获取用户的状态

    获取美国用户所在州的最有效方法是什么 HTML5 地理定位是否是一种无需涉及谷歌地图的选项 这里有几个 JavaScript 和 JSON 的例子 在jQuery http jquery com 使用IP查找方法 借助IPinfoDB ht
  • UITableView - 使用 Swift 注册类

    其他人在使用时遇到问题吗tableView registerClass方法与斯威夫特 它不再为我提供代码补全 如果手动键入 我也不能使用它 但它仍然在标题中 它对我来说非常有效 self tableView register UITable
  • CGAL:继承和内核

    CGAL问题 我正在尝试向点类添加一个属性 我想第一步是继承一个内核并用我自己的从 CGAL 继承的点类替换点类 但只是想迈出这小小的第一步 我就遇到了麻烦 编辑 根据下面的评论 我将继承更改为手册中描述的方式 下面的代码给出了以下编译错误
  • 程序集 32 位打印显示在 qemu 上运行的代码,无法在真实硬件上运行

    我已经用 x86 汇编语言编写了一小段在裸硬件上运行的代码 此时 它已启用受保护的 32 位模式 然而 我遇到了与屏幕打印有关的问题 我读到 要在不中断的情况下执行此操作 可以将字符加载到特殊的内存区域 即 RAM 地址 0xb8000 知
  • C++ new、delete 和函数

    这对我来说有点不清楚 所以 如果我有一个函数 char test int ran char ret new char ran process return ret 然后多次调用它 for int i 0 i lt 100000000 i c
  • 搜索过滤器:最少字符数

    这是我用于至少 3 个字符检查的简单代码 如果查询是全数字的 我想例外 代码还可以选择按案例 ID 进行搜索 案例 ID 少于 3 个字符 感谢帮助 用这个 if strlen POST Search gt 3 is numeric POS
  • AutoMapper:将接口映射到抽象类 - 这可能吗?

    我在用着自动映射器 http automapper codeplex com在我的应用程序的不同层之间映射对象 一方面 我有一个如下所示的界面 public interface MyRepo IEnumerable
  • 如何获得 OxyPlot 中的所有颜色?

    我有一个问题 我在 WPF C 中使用 OxyPlot 我需要将所有颜色设置为系列的 MarkerType 和 MarkerStroke 我怎样才能获得所有颜色 Green IndianRed 等是静态 OxyColors 类中的静态字段
  • javax.el.PropertyNotFoundException:在 JSP 中使用 JSTL [重复]

    这个问题在这里已经有答案了 我有一个 JSP 我尝试使用 JSTL 标记来显示类的内存实例中的数据 该数据由一系列字符串组成 其中每个字符串都是 RSS 提要的地址 在 JSP 中 我有以下代码 table border 1 tr tr t
  • view.invalidate() 无法重绘 imageview

    好吧 伙计们 这可能听起来很愚蠢 但我已经用头撞键盘有一段时间了 试图找出为什么这不会刷新 基础知识 我有一个小示例应用程序 我正在测试它是否可以将图像围绕一个点旋转 X 度 并一次显示一个度以制作平滑的动画 所以我有一个很棒的示例 我发现
  • 如何根据键名合并2个数组并根据合并后的值进行排序?

    假设我有两个列表 const listA apple 100 banana 50 pearl 10 cherry 5 kiwi 3 const listB peach 30 apple 15 kiwi 10 mango 5 问题是如何将两个
  • 为什么导航在版本 2.4.1 的导航抽屉活动模板中不起作用?

    使用Android Studio 2021 1 1 使用导航抽屉活动创建一个新项目 使用导航抽屉活动模板创建了一个默认的 Android 应用程序 在项目中添加了一个设置片段来测试action settings菜单和配置菜单项 被覆盖onO