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

Android 我可以在导航组件中使用多个NavHostFragments吗?,android,android-architecture-components,android-architecture-navigation,Android,Android Architecture Components,Android Architecture Navigation,如果你在理解以下段落时有困难,请看我制作的流程图 我目前正在制作一个有3个顶级目的地的notes应用程序。其中一个顶级目的地(NotesList)显示用户创建的注释列表。NotesList有一个filter按钮,它会显示一个带有FilterMenu目的地的底部模式表。FilterMenu有一个搜索按钮,单击该按钮时,将工作表的内容替换为搜索目标;还有一个名为tags的按钮,单击该按钮时,将工作表的内容替换为包含与所有注释关联的标记列表的片段(TagList destination) 蓝色的一切

如果你在理解以下段落时有困难,请看我制作的流程图

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

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

过滤器菜单、搜索和标记列表显示在模式表中。这意味着NotesList包含这些片段,并且不会被它们替换。它们存在于比记事本列表小的屏幕区域中。如果我使用导航,片段将相互替换


我能用两台导航主机吗?一个用于顶级目的地,一个用于模式表中的内容?如果是,我将如何实施?如果没有,在这种情况下建议做什么?

创建两个NavHostFragment的简单方法是创建另一个navigation.xml文件

例如,在我的应用程序中,我有两个navHostsFragments

我为导航流定义了第一个,因此当用户进入应用程序时,他会转到登录片段,即navHostFragment

用户登录后,他将被转移到包含我的新navHostFragment的mainActivity

这样,每当我启动包含新navHostFragment的新活动时


希望这有助于

您可以创建两个导航图来实现所需的行为。一个用于顶级目的地,另一个用于模式表。他们需要独立,彼此之间没有任何联系。不能只使用一个导航图,因为“导航曲面”是不同的。对于主导航,它是活动,对于模式底部工作表,它是底部工作表窗口(对于底部工作表对话框片段,它实际上是另一个窗口)

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

  • main_nav.xml
    保存
    设置
    注释列表
    垃圾桶
  • filter\u nav.xml
    保存
    filter菜单
    搜索
    标记列表
如果您不想在顶层进行反向导航,您甚至可以使用片段事务在没有导航控制器的情况下进行顶层导航

因此,基本上您需要一个
(底页)对话框片段
,它需要一个独立于主/其他
导航主机
的独立
导航主机。您可以通过以下类实现这一点:

对话框\u片段\u模式\u底部\u 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"/>
我们在这里有两个技巧:

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

  • 我们需要覆盖对话框的反向导航。对话框是活动顶部的一个单独窗口,因此不会调用
    活动的
    onBackPressed()
    。相反,我们添加了一个
    OnKeyListener
    ,当释放后退按钮(
    ACTION\u UP
    )时,我们使用
    NavController
    检查它是否可以弹出后退堆栈(返回)。如果它能弹出后台堆栈,我们将返回true,从而使用后台事件。对话框保持打开,导航控制器后退一步。如果它已经在起始点,当我们返回false时,对话框将关闭

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

    val dialog = ModalBottomSheetDialogFragment()
    dialog.show(childFragmentManager, "filter-menu")
    
    您还可以在
    main\u nav
    中将
    ModalBottomSheetDialogFragment
    添加为
    目的地,但我没有对此进行测试。此功能目前仍在alpha中,并在导航2.1.0-alpha03中引入。因为这仍然是alpha版本,API可能会更改,我个人会使用上面的代码来显示对话框。一旦超出alpha/beta,最好使用
    main_nav.xml
    中的目的地。从用户的角度来看,显示对话框的不同方式没有区别


    我使用您的导航结构创建了一个示例应用程序。它有两个独立的图形在两个级别上的工作返回导航。你可以看到它在工作。我使用了一个底部栏作为主导航,但你可以用抽屉代替它。

    我认为你的方法有效,因为你有多个活动我有3个活动,包含20多个片段,所以每次我启动一个新的大流时,我都会创建新的活动,这是我发现的唯一有多个navHostFragments的方法。好吧,问这个问题的人和我只有一项活动。问题是特定于一个片段是模态的,并且必须从该模态中导航,如果需要帮助,请告诉我@蒂姆·卡斯特利金斯,你有没有找到时间来看看这个?如果有效,请让我知道。我会接受这个答案。我今天就去做,昨天我在做其他的事情。事实上,我从Ivan Milisavljevic那里得到了一些其他的建议,看看他的演示,我将他对和模态片段类的使用与您的运行时navhostfragment实例化结合在一起,听起来似乎很好!这就是我所说的“您还可以在main_nav中将ModalBottomSheetDialogFragment添加为对话框目标”。对不起,这里不够清楚!我更新了答案以改进这一点。
    目标仍处于alpha状态,API可能会更改,直到它处于beta状态。我知道show()和
    val dialog = ModalBottomSheetDialogFragment()
    dialog.show(childFragmentManager, "filter-menu")