gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 23:25:18 28 4
gpt4 key购买 nike

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

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

enter image description here

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

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

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

最佳答案

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

理论上这很容易实现:

  • main_nav.xml持有 Settings , NoteListTrash
  • filter_nav.xml持有FilterMenu , Search , 和 TagList

如果您不想在顶层返回导航,您甚至可以在没有导航 Controller 的情况下使用 fragment 事务进行顶层导航。

所以基本上你需要一个 (BottomSheet)DialogFragment需要单独的 NavHost独立于主要/其他NavHost .您可以通过以下类(class)实现此目的:

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 顶部的一个单独窗口,因此 ActivityonBackPressed()不被调用。相反,我们添加一个 OnKeyListener当返回按钮被释放时( ACTION_UP )我们检查 NavController它是否可以弹出回栈(返回)。如果它可以弹出返回堆栈,我们返回 true 并因此消耗返回事件。对话框保持打开状态,NavController退一步。如果它已经在起点,则对话框将在我们返回 false 时关闭。

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

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

您也可以添加 ModalBottomSheetDialogFragment作为 <dialog>目的地 main_nav ,但我没有对此进行测试。此功能目前仍处于 alpha 阶段,并在导航 2.1.0-alpha03 中引入。因为这仍处于 alpha 阶段,所以 API 可能会发生变化,我会亲自使用上面的代码来显示对话框。一旦超出 alpha/beta,使用 main_nav.xml 中的目的地应该是首选方式。从用户的角度来看,显示对话框的不同方式没有区别。

我使用您的导航结构创建了一个示例应用程序 here on GitHub .它使用两个独立的图表在两个级别上进行反向导航。你可以看到它工作here on Youtube .我使用底部栏作为主导航,但您可以将其替换为抽屉。

关于android - 我可以在导航组件中使用多个 NavHostFragment 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51523225/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com