我可以在导航组件中使用多个 NavHostFragment 吗?

2024-05-09

如果您难以理解以下段落,请查看我制作的流程图。

我目前正在制作一个带有 3 个顶级目的地的笔记应用程序。顶级目标之一(NotesList)显示用户创建的注释列表。 NotesList 有一个过滤器按钮,可显示带有 FilterMenu 目标的底部模式表。 FilterMenu 有一个搜索按钮,单击该按钮,将工作表的内容替换为搜索目标;还有一个名为标签的按钮,单击该按钮,将工作表的内容替换为包含与所有注释关联的标签列表的片段(TagList目的地)。

蓝色的一切都是顶级目的地。紫色的所有内容都出现在模态表中。

FilterMenu、Search 和TagList 显示在模式表中。这意味着 NotesListcontains这些碎片并不会被它们取代。它们存在于比 NotesList 小的屏幕区域中。如果我使用导航,片段将相互替换。

我可以使用两个 NavHost 吗?一个用于顶级目的地,另一个用于模态表中的内容?如果是这样,我将如何实施?如果没有,在这种情况下建议做什么?


您可以创建两个导航图来实现您想要的行为。一个用于顶级目的地,第二个用于模式表。它们需要独立,彼此之间没有任何联系。您不能仅使用一个导航图,因为“导航表面”是不同的。对于主导航,它是活动,对于模态底部工作表,它是底部工作表窗口(在 BottomSheetDialogFragment 的情况下,它实际上是一个不同的窗口)。

理论上这可以很容易实现:

  • main_nav.xml holds Settings, NoteList and Trash
  • filter_nav.xml持有FilterMenu, Search, and TagList

如果您不想在顶层进行后退导航,您甚至可以使用片段事务在没有导航控制器的情况下进行顶层导航。

所以基本上你需要一个(BottomSheet)DialogFragment这需要一个单独的NavHost独立于主要/其他NavHost。您可以通过以下课程来实现这一目标:

dialog_fragment_modal_bottom_sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/filterNavHost"/>

ModalBottomSheetDialogFragment .kt

class ModalBottomSheetDialogFragment : BottomSheetDialogFragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
        inflater.inflate(R.layout.dialog_fragment_modal_bottom_sheet, container, false)

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

        // We can't inflate the NavHostFragment from XML because it will crash the 2nd time the dialog is opened
        val navHost = NavHostFragment()
        childFragmentManager.beginTransaction().replace(R.id.filterNavHost, navHost).commitNow()
        navHost.navController.setGraph(R.navigation.filter_nav)
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return super.onCreateDialog(savedInstanceState).apply {
            // Normally the dialog would close on back press. We override this behaviour and check if we can navigate back
            // If we can't navigate back we return false triggering the default implementation closing the dialog
            setOnKeyListener { _, keyCode, event ->
                if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
                    view?.findNavController()?.popBackStack() == true
                } else {
                    false
                }
            }
        }
    }
}

我们在这里做了两个技巧:

  1. 我们需要手动创建NavHost分段。如果我们直接将其放入 XML 中,则第二次打开对话框时会崩溃,因为 ID 已被使用

  2. 我们需要覆盖对话框的后退导航。对话框是位于 Activity 之上的一个单独窗口,因此Activity's onBackPressed()没有被叫到。相反,我们添加一个OnKeyListener当释放后退按钮时(ACTION_UP)我们检查NavController是否可以弹出返回堆栈(返回)。如果它可以弹出后退堆栈,我们将返回 true,从而消耗后退事件。对话框保持打开状态并且NavController退一步。如果它已经在起点,当我们返回 false 时,对话框将关闭。

您现在可以在对话框内创建嵌套图,而不必关心外部图。要显示带有嵌套图的对话框,请使用:

val dialog = ModalBottomSheetDialogFragment()
dialog.show(childFragmentManager, "filter-menu")

您还可以添加ModalBottomSheetDialogFragment as <dialog>目的地在main_nav,但我没有对此进行测试。该功能目前仍处于 alpha 版本,并在 navigation 2.1.0-alpha03 中引入。由于这仍处于 alpha 阶段,API 可能会发生变化,我个人会使用上面的代码来显示对话框。一旦超出 alpha/beta,请使用以下目的地:main_nav.xml应该是首选方式。从用户的角度来看,显示对话框的不同方式没有什么区别。

我使用您的导航结构创建一个示例应用程序在 GitHub 上 https://github.com/crysxd/NestedNavHostsExample。它具有两个独立图表的两个级别的工作返回导航。你可以看到它正在运行在 YouTube 上 https://youtu.be/lnyDB7DH9KM。我使用底部栏作为主导航,但您可以用抽屉替换它。

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

我可以在导航组件中使用多个 NavHostFragment 吗? 的相关文章

  • Android 中用虚拟键盘捕捉按键按下的情况?

    使用物理键盘 您可以使用按键监听器 http developer android com reference android text method KeyListener html 就像是 myEditText setOnKeyListe
  • Android 上有哪些字体可用? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我知道安卓有一个字体集合 http www ascenderfonts com store search
  • 强制用户在 Android 中的 EditText 中输入内容

    我的活动中有几个编辑文本 我希望我的用户在提交表单之前正确输入 我该怎么做 我还有旋转器和 RadioGroup 按钮 你可以加验证在提交按钮上单击 private boolean validateFields int yourDesire
  • Android 自定义视图不能以正确的方式处理透明度/alpha

    我正在绘制自定义视图 在此视图中 我使用两个不同的绘画和路径对象在画布上绘画 我基本上是在绘制两个重叠的形状 添加 Alpha 后 视图中重叠的部分比图像的其余部分更暗 这是不希望的 但我不知道如何解决它 这是我的代码片段 用于展示我如何在
  • 如何从一个代码库创建多个 Android 应用

    我有一个 Android 代码库 它使用带有设置的 API 来获取多个应用程序的不同数据 所有应用程序都使用相同的代码库 但进行一两个设计调整 那么如何重用主代码库而不必每次都复制整个 Android 项目呢 iPhone 在同一个项目中使
  • Firestore - RecycleView - 图像持有者

    我不知道如何编写图像的支架 我已经设置了 2 个文本 但我不知道图像的支架应该是什么样子 你能帮我告诉我图像的文字应该是什么样子才能正确显示吗 holder artistImage setImageResource model getArt
  • Renderscript 示例构建错误

    所以我想尝试使用 RenderScript 的示例 并在 Eclipse 中导入了 HelloWorld 但它给了我这样的错误 2011 10 25 13 10 48 HelloWorld home mileoresko workspace
  • 以编程方式更新 Android 中的联系人姓名和电话号码

    我创建一个应用程序来读取 更新 删除联系人详细信息 这是更新联系人姓名和电话号码的问题 有人可以帮助我吗 我该怎么做 我正在使用以下代码 但它不起作用 Override public View onCreateView LayoutInfl
  • 应用内结算错误

    我的 UNMANAGED 应用内购买无法正常工作 在它完美运行之前 我可以使用测试帐户成功购买 但它突然不起作用了 因为我记得我对商家帐户所做的只是添加更多 2 4 个测试帐户 添加后 我的应用内购买将不起作用 所以我更新了公钥并上传了一个
  • finish() 完成活动但它仍然在后台

    我有一个关于 android studio 中活动的 finish 方法的问题 我有这个简单的代码 public class MainActivity extends AppCompatActivity Override protected
  • 如何在进入新活动之前终止线程和处理程序

    大家好 在我尝试清理处理程序时 这段代码可能有点混乱 因为我一直在尝试追踪崩溃发生的位置 我有一个对话框活动 显示密码输入 进度条由线程和处理程序动画显示 似乎当我试图查看进度条是否完成并尝试终止线程时 当我尝试进入新活动时 我这样做的方式
  • java.lang.IllegalArgumentException:找不到片段的 id 0x1020002 (android:id/content) 的视图

    我正在尝试从一个片段移动到另一个片段 它在片段事务期间显示以下错误 java lang IllegalArgumentException No view found for id 0x1020002 android id content f
  • Vimeo 视频在 Android 6 设备上停止播放

    我正在尝试在我的应用程序中播放 Vimeo 的视频 问题是在 Android 6 设备上 视频会在一定时间后停止播放 在 API 较低的设备上一切正常 时间取决于质量 对于下面提供的网址的视频 播放一定分钟 1 到 3 视频质量有多低 播放
  • Android 从命令行停止模拟器

    这个问题与如何通过命令行关闭Android模拟器 https stackoverflow com questions 5912403 how to shut down android emulator via cmd 但是 在尝试第一个答案
  • onBackPressed 隐藏 不破坏 Activity

    我知道如何取消后退按键 以便活动 主窗口保持可见 public void onBackPressed return 我的目标是隐藏该活动 但是 在没有完成它的情况下 您如何在 onBackPressed 事件中做到这一点 即我想达到 onP
  • 在 Honeycomb Android 3.0 中显示 Action Bar 菜单项的图标

    我正在使用 Honeycomb android 3 0 开发 Android 应用程序 我正在尝试在 Action Bar 中显示菜单 菜单有一个图标和标题 当我们单击菜单项时 它会以下拉列表的形式显示其项目 它是下拉列表中带有项目名称但不
  • Android:解析 XML 数据的最佳解析器 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在开发一个应用程序 其中我第一次要解析来自远程服务器的 xml 文件中的数据 但我无法选择哪个解析器是有效的或最适合解析的 因为我知道主要有
  • 在没有 Wifi 的情况下获取 Android 设备的 MAC 地址

    如何获取没有 Wifi 接口的 Android 设备 例如 Android 模拟器 的网络接口的 MAC 地址 通过WifiManager返回获取的WifiInfonull EDIT 更清楚地说 我必须与本地网络上的现有网络协议 不是我设计
  • 在 Android 中使用 iText 将图像添加到特定位置

    我想使用 Android 中的 iText 将图像添加到 PDF 文件中的特定位置 这是一个可填写的表单 我添加了作为图像占位符的文本框 我想要做的就是像这样获取该文本框和图像 public class FormFill public st
  • Android 和 Java 中绘制椭圆的区别

    在Java中由于某种原因Ellipse2D Double使用参数 height width x y 当我创建一个RectF在Android中参数是 left top right bottom 所以我对适应差异有点困惑 如果在 Java 中创

随机推荐

  • R:邻接表到邻接矩阵

    Bonjour 我想将邻接列表 3 列 转换为邻接矩阵 在这个论坛中 我找到了多个有关如何将边列表转换为邻接矩阵的示例 我成功地为两列列表做到了这一点 我已经尝试了在网上可以找到的所有解决方案 但似乎我错过了一小步 我尝试过的 我的变量是用
  • 存储过程上的 OdbcCommand - 输出参数上出现“未提供参数”错误

    我正在尝试执行存储过程 通过 ODBC 驱动程序针对 SQL Server 2005 但收到以下错误 过程或函数 GetNodeID 需要参数 ID 但未提供该参数 ID 是我的过程的 OUTPUT 参数 在存储过程中指定了一个输入 mac
  • GeoJSON 要素坐标未显示在 OpenLayers 地图上

    我正在尝试显示一个GeoJSON地图上的多边形 我使用了 OpenLayers 提供的示例以及以下数据 但仅显示第二个多边形 var geojsonObject type FeatureCollection crs type name fe
  • InvalidArgumentException:消息:无效参数:“using”必须是字符串

    我对 python 很陌生 试图创建可重用的代码 当我尝试通过传递 Login 类下使用的所有参数来调用 test main py 中的 Login 类和函数 login user 时 我收到错误 InvalidArgumentExcept
  • HATEOAS 与 PUT/POST 链接

    代表 HATEOAS 链接的最佳方式是什么POST PUT PATCH在资源上 这些操作具有有效负载 但我们无法选择在 HATEOAS 链接中表示有效负载 因为它们不是预先确定的并且可能很重 那么仅仅指定终点并指定操作就足够了吗 对于 HA
  • 找到的构造函数都无法使用可用的服务和参数 Autofac 进行调用

    我已阅读并编码以下示例 http timschreiber com 2015 01 14 persistence ignorant asp net identity with patterns part 1 http timschreibe
  • Angular 2 最终版本路由器单元测试

    如何使用 karma 和 jasmine 对 Angular 2 0 0 版中的路由器进行单元测试 这是我的旧单元测试在版本 2 0 0 beta 14 中的样子 import it inject injectAsync beforeEac
  • Android 简单 TextView 动画

    我有一个 TextView 我想倒计时 3 2 1 发生了事情 为了使其更有趣 我希望每个数字都以完全不透明开始 然后淡出至透明 有没有一种简单的方法可以做到这一点 尝试这样的事情 private void countDown final
  • 从 SQL Server 2008 的 .mdf 和 .ldf 文件恢复数据库

    由于某种原因 我必须卸载 SQL Server 2008 R2 但在此之前我复制了两个文件 mdf and ldf 我的数据库来自 C Program Files x86 Microsoft SQL Server MSSQL10 50 MS
  • 如何使用 jira-python 设置 fixVersions 字段

    我正在尝试使用 jira python 模块 http jira python readthedocs org en latest 更新现有的 JIRA 具体来说 我正在尝试设置问题的fixesVersion 列表 我已经尝试了一段时间但没
  • 序列化和反序列化 Visual Studio 解决方案文件 - 或以编程方式编辑?

    我想以编程方式添加和删除项目 解决方案文件夹和其他项目 例如解决方案的资源文件 但我不确定最好的方法是什么 对于那些不知道的人 高度简化 解决方案文件 sln 通常如下所示 Microsoft Visual Studio Solution
  • 使用 google.protobuf.Timestamp 在 Go 中解析带有时区偏移的日期时间戳

    我正在创建一个将使用 GRPC 和 protobuf 的 Go 应用程序 我的 RPC 服务应获取包含类型的消息google protobuf Timestamp 解析它并最终将其保存在数据库中或对其执行更多操作 我对什么被认为是该类型的有
  • Coredata错误setObjectForKey:对象不能为nil

    我正在尝试检查我的核心数据存储中是否有任何数据作为我的应用程序的恢复类型 基本上 如果用户处于最终视图 则 coredata 中会有一些数据不断更新 因此 他们处于最终视图中 然后应用程序崩溃 或者他们将其置于睡眠状态 然后应用程序从内存中
  • 如何使用flyway将数据从一个DB迁移到另一个DB?

    我在不同的服务器上有两个 postgreSql DB 比如说 A 和 B 我可以使用 Flyway 一些如何将所有数据从 DB A 复制到新设置且为空的 B 如果有人指出我正确的方向和工具 这将很有帮助 要求是通过某种工具自动化将数据从一个
  • 如何在动作脚本 3 中设置/访问外部 swf 文件的动态文本字段?

    我正在处理一个 fla 文件 其中添加了一个 swf 文件 我如何在该 swf 文件的动态文本上设置文本 有没有直接设置文本的方法 我不想在 url 中作为参数传递 我试过这样 var rq URLRequest new URLReques
  • 部署在 Azure 中时在 EF 迁移中使用更新数据库

    上下文 我在 Azure 中部署了 ASP NET MVC4 解决方案 我的 MSSQL Server 数据库也在 Azure 中 我目前的部署方式是这样的 在 web config 中 我将连接字符串从本地数据库 sdf 更改为 azur
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 任何人都知道 JQuery 插件可以生成类似于 geni.com 上的树形菜单

    大家好 我花了几个小时寻找一个 Jquery 插件来生成像 geni com 上那样的树形菜单模块 如果有人知道 Jquery 中的这样的插件或脚本 请让我知道或指导我如何使用 Jquery 开发这样的功能 请检查我正在寻找什么http w
  • 如何返回每个另一个节点属性的最大计数

    我需要计算一位作曲家的音乐作品每十年被演奏了多少次 然后只返回每十年演奏次数最多的一首作品 除了过滤除每十年最高计数之外的所有内容之外 该密码可以执行所有操作 match c Composer CREATED BY w Work lt 2
  • 我可以在导航组件中使用多个 NavHostFragment 吗?

    如果您难以理解以下段落 请查看我制作的流程图 我目前正在制作一个带有 3 个顶级目的地的笔记应用程序 顶级目标之一 NotesList 显示用户创建的注释列表 NotesList 有一个过滤器按钮 可显示带有 FilterMenu 目标的底