如何使用FragmentContainerView和Navigation组件?

76

从先前的版本更新到 Navigation 2.2.0-beta01 后,lint 给出警告,建议使用 FragmentContainerView 替换 <fragment> 标签。

然而,仅替换标签似乎会防止导航图被膨胀。

根据 2.2.0-alpha01FragmentContainerView 在内部被使用。我们应该忽略 lint 警告吗?


activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Lint warning: "Replace the <fragment> tag with FragmentContainerView. -->
    <fragment
        android:id="@+id/nav_host_main"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph_main"/>

    <!-- other elements -->

</androidx.constraintlayout.widget.ConstraintLayout>

14
使用 FragmentContainerView 有什么优势? - IgorGanapolsky
@IgorGanapolsky 请参阅官方文档:https://developer.android.com/reference/androidx/fragment/app/FragmentContainerView - Eugen Pechanec
@EugenPechanec 为什么我们需要这个,当我们已经有Jetpack Navigation了呢? - IgorGanapolsky
1
@IgorGanapolsky 不错的问题,Jetpack Navigation 可以在 fragment 之间导航。当片段位于“FragmentContainerView”和其他任何容器布局中时,片段_转换_(进入/退出动画)的行为会有所不同。这些差异在上面链接的 FCV 文档中有描述。基本上,FCV 应该使过渡效果更符合您的预期。或者说,Jetpack Navigation 依赖于 fragments 。如果 Fragments 出现问题,您可以获取修复后的新版本 Fragments 库或等待 Jetpack Navigation 的新版本,该版本依赖于已修复的 Fragments。 - Eugen Pechanec
2
@EugenPechanec 我明白你的意思。然而,当Google明确倡导Jetpack Navigation时,开发人员需要跟进两个不同的API是一件麻烦事。 - IgorGanapolsky
4个回答

46

如果你只是简单地用 <androidx.fragment.app.FragmentContainerView>替换fragment,仍然会有一个bug会抛出异常。截至目前为止,许多Google工程师在这个bug thread中说明的解决方法是更改你的activity中的代码:

val navHostFragment = supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController

1
是的!只需这两行代码,我的导航就能正常工作了,不需要做任何其他更改。 - Alexey Simchenko
1
这个答案应该用正确的方式来表述。 - Lucas Orso
1
这是正确的答案。 - Raghav Satyadev

21

重要提示! FragmentContainerView 的不同版本存在已知问题。在使用之前,请查看更新记录。请阅读错误修复并使用最新版的库。


目前,您还应该声明对 Fragment 1.2.0-beta02 的依赖,因为它包含了此用例的修复。

implementation "androidx.fragment:fragment:1.2.0-beta02"

版本1.2.0-beta02

2019年10月11日

修复的漏洞

修复了一个问题,即Fragment的onInflate()未从FragmentContainerView接收正确的属性,导致像NavHostFragment这样的情况出现问题。 (b/142421837)

来源:https://developer.android.com/jetpack/androidx/releases/fragment#1.2.0-beta02


@glend 请准备一个最小化的项目来复现该问题,并在官方问题跟踪器(https://issuetracker.google.com/issues/new?component=409828&template=1093757)上报告。谢谢! - Eugen Pechanec

15
NavigationBasicSample 已更新至 2.2.0-alpha01,但仍使用 fragment 标签。而 NavigationAdvancedSample 展示了如何使用 FragmentContainerView,但导航图是在代码中加载的(它们有几个不同的图),相应的主机 Fragment 被添加到 FragmentContainerView 中。所以,如果我们想要自动加载,则此时可以忽略警告。

我在示例中也注意到了这一点。似乎添加最新的“Fragment”依赖项可以解决lint警告。 - user12194200
为什么我们需要FragmentContainerView? - IgorGanapolsky
4
我检查了AdvancedSample中的代码,它让我感到恶心! 我不知道为什么Google团队要以这种尴尬的方式创建和破坏东西。现在我可能不得不复制扩展函数Today,但这可能会因导航库的某些更新而再次破坏Tomorrow。 这太糟糕了!! - sud007

5

使用Java

NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager()
                .findFragmentById(R.id.nav_host_fragment);
navController = navHostFragment.getNavController();

2
这可能是一个答案,但添加更多信息将有助于您的帖子质量。 https://stackoverflow.com/help/how-to-answer - haydnD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接