<androidx.fragment.app.FragmentContainerView> 与 <fragment> 作为 NavHost 的视图
<androidx.fragment.app.FragmentContainerView> vs <fragment> as a view for a NavHost
当使用 androidx.fragment.app.FragmentContainerView
作为 navHost 而不是常规 fragment
应用时,方向更改后无法导航到目的地。
我收到以下错误:
java.lang.IllegalStateException: no current navigation node
是否有我应该知道的关于正确使用它的陷阱,或者我使用导航组件的方式不正确?
简单 activity xml 视图:
...
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:navGraph="@navigation/nav_simple" />
...
导航代码:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_legislator.xml"
app:startDestination="@id/initialFragment">
<fragment
android:id="@+id/initialFragment"
android:name="com.example.fragmenttag.InitialFragment"
android:label="Initial Fragment"
tools:layout="@layout/initial_fragment">
<action
android:id="@+id/action_initialFragment_to_destinationFragment"
app:destination="@id/destinationFragment" />
</fragment>
<fragment
android:id="@+id/destinationFragment"
android:name="com.example.fragmenttag.DestinationFragment"
android:label="Destination Fragment"
tools:layout="@layout/destination_fragment" />
</navigation>
这是一个 github 存储库,您可以在其中轻松重现错误:https://github.com/dmytroKarataiev/navHostBug
当没有图形集并且您尝试调用 navigate()
时,会出现 no current navigation node
错误。如果它仅在您使用 FragmentContainerView
时发生并且在配置更改后发生,那么这将与 this bug 相关,后者已修复并计划与 Navigation 2.2.0-rc03 一起发布。
要解决此问题,您可以切换回 <fragment>
或删除 app:navGraph="@navigation/nav_simple"
并改为调用 navController.setGraph(R.navigation.nav_simple)
.
我没有看到任何解释为什么要用 FragmentContainerView 替换 Fragment 视图。这就是添加此答案的原因:
在 activity 中托管片段的一种常见模式是使用 FrameLayout。 Android 社区多年来一直这样做,但现在这种情况将会改变。 androidx 团队引入了这个名为 FragmentContainerView 的新视图来为您执行此操作。
您所要做的就是用 FragmentContainerView 替换您的 FrameLayout,一切都应该开箱即用,您无需更改处理片段事务的方式。
这里获得的好处是改进了对所谓的片段 z 排序的处理。这是他们使用的示例,但这基本上意味着,例如,两个片段之间的退出和进入转换不会相互重叠。相反,这个 FragmentContainerView 将首先启动退出动画,然后是进入动画。
如果你问这个能代替标签吗?那么答案是肯定的。您所要做的就是在定义 FragmentContainerView 时添加 android:name="your_class_name" ,它将在后台使用 FragmentTransaction 来构建和显示您的片段。这意味着您可以稍后使用片段事务来替换它。
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.frag_splash, container, false)
}
也许你忘记了上面的第三个“false”参数。只有这三个参数onCreateView
fun 可以接受。
android developer website
图片来自:https://developer.android.com/reference/androidx/fragment/app/FragmentContainerView
// drawer layout that I pass is the id of the layout in the activity from which I move to fragment//
SacnFragment sacnFragment = new SacnFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.drawer_layout, sacnFragment);
transaction.addToBackStack(null);
transaction.commit();
当使用 androidx.fragment.app.FragmentContainerView
作为 navHost 而不是常规 fragment
应用时,方向更改后无法导航到目的地。
我收到以下错误:
java.lang.IllegalStateException: no current navigation node
是否有我应该知道的关于正确使用它的陷阱,或者我使用导航组件的方式不正确?
简单 activity xml 视图:
...
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:navGraph="@navigation/nav_simple" />
...
导航代码:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_legislator.xml"
app:startDestination="@id/initialFragment">
<fragment
android:id="@+id/initialFragment"
android:name="com.example.fragmenttag.InitialFragment"
android:label="Initial Fragment"
tools:layout="@layout/initial_fragment">
<action
android:id="@+id/action_initialFragment_to_destinationFragment"
app:destination="@id/destinationFragment" />
</fragment>
<fragment
android:id="@+id/destinationFragment"
android:name="com.example.fragmenttag.DestinationFragment"
android:label="Destination Fragment"
tools:layout="@layout/destination_fragment" />
</navigation>
这是一个 github 存储库,您可以在其中轻松重现错误:https://github.com/dmytroKarataiev/navHostBug
当没有图形集并且您尝试调用 navigate()
时,会出现 no current navigation node
错误。如果它仅在您使用 FragmentContainerView
时发生并且在配置更改后发生,那么这将与 this bug 相关,后者已修复并计划与 Navigation 2.2.0-rc03 一起发布。
要解决此问题,您可以切换回 <fragment>
或删除 app:navGraph="@navigation/nav_simple"
并改为调用 navController.setGraph(R.navigation.nav_simple)
.
我没有看到任何解释为什么要用 FragmentContainerView 替换 Fragment 视图。这就是添加此答案的原因:
在 activity 中托管片段的一种常见模式是使用 FrameLayout。 Android 社区多年来一直这样做,但现在这种情况将会改变。 androidx 团队引入了这个名为 FragmentContainerView 的新视图来为您执行此操作。
您所要做的就是用 FragmentContainerView 替换您的 FrameLayout,一切都应该开箱即用,您无需更改处理片段事务的方式。
这里获得的好处是改进了对所谓的片段 z 排序的处理。这是他们使用的示例,但这基本上意味着,例如,两个片段之间的退出和进入转换不会相互重叠。相反,这个 FragmentContainerView 将首先启动退出动画,然后是进入动画。
如果你问这个能代替标签吗?那么答案是肯定的。您所要做的就是在定义 FragmentContainerView 时添加 android:name="your_class_name" ,它将在后台使用 FragmentTransaction 来构建和显示您的片段。这意味着您可以稍后使用片段事务来替换它。
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.frag_splash, container, false)
}
也许你忘记了上面的第三个“false”参数。只有这三个参数onCreateView
fun 可以接受。
android developer website
图片来自:https://developer.android.com/reference/androidx/fragment/app/FragmentContainerView
// drawer layout that I pass is the id of the layout in the activity from which I move to fragment//
SacnFragment sacnFragment = new SacnFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.drawer_layout, sacnFragment);
transaction.addToBackStack(null);
transaction.commit();