使用导航组件,使用嵌套在其他NavHostFragments中的NavHostFragments

时间:2018-12-09 02:46:12

标签: android android-navigation android-architecture-navigation

请注意,我在这里不是在谈论Nested Navigation Graphs。我特别在谈论使用NavHostFragments作为其他NavHostFragments的子节,以及使用NavigationComponent在子片段和父片段之间来回转换。话虽这么说...

我们如何在其他NavHostFragments内部的NavHostFragments中正确使用导航组件?

例如:假设我有一个MainActivity,其布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            style="@style/Toolbar"/>
    </android.support.design.widget.AppBarLayout>
    <fragment
        android:id="@+id/navHost"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />
</LinearLayout>

主要活动的ID为NavHostFragment的{​​{1}}使用导航图navHost,如下所示:

nav_graph

实质上,<?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_graph" app:startDestination="@id/fragmentA"> <fragment android:id="@+id/fragmentA" android:name="com.example.nestednavfragmentstest.FragmentA" android:label="FragmentA" tools:layout="@layout/fragment_a"> <action android:id="@+id/action_fragmentA_to_fragmentB" app:destination="@id/fragmentB"/> </fragment> <fragment android:id="@+id/fragmentB" android:name="com.example.nestednavfragmentstest.FragmentB" android:label="FragmentB" tools:layout="@layout/fragment_b"/> </navigation> 可以从navHost导航到FragmentA(例如,单击按钮)。但是等等,还有更多...

如果我想FragmentB包含它自己的内部Fragment B怎么办? xml可能看起来像这样:

NavHostFragment

如您所见,<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Fragment B" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <fragment android:id="@+id/embeddedNavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="50dp" app:defaultNavHost="true" app:layout_constraintTop_toBottomOf="@id/textView" app:layout_constraintBottom_toBottomOf="parent" app:navGraph="@navigation/inner_nav_graph"/> </android.support.constraint.ConstraintLayout> 有自己的FragmentB,名为NavHostFragment,其navGraph如下所示:

embeddedNavHostFragment

如您所见,该内部<?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/inner_nav_graph" app:startDestination="@id/innerFragmentB1"> <fragment android:id="@+id/innerFragmentB1" android:name="com.example.nestednavfragmentstest.InnerFragmentB1" android:label="InnerFragmentB1" tools:layout="@layout/inner_fragment_b1"> <action android:id="@+id/action_innerFragmentB1_to_innerFragmentB2" app:destination="@id/innerFragmentB2"/> </fragment> <fragment android:id="@+id/innerFragmentB2" android:name="com.example.nestednavfragmentstest.InnerFragmentB2" android:label="InnerFragmentB2" tools:layout="@layout/inner_fragment_b2"/> </navigation> 用于在两个内部片段NavHostFragmentInnerFragmentB1之间导航。现在是主要问题...

InnerFragmentB2中覆盖onSupportNavigateUp()的正确方法是什么?

最初,我做了这样的事情:

MainActivity

但是在某些情况下,这会由于后堆栈不一致而导致崩溃。例如:

  1. override fun onSupportNavigateUp(): Boolean { return findNavController(R.id.navHost).navigateUp() } MainActivity中的片段A开头。
  2. 通过navHost导航到action_fragmentA_to_fragmentB(以B中的B1开头)
  3. 通过embeddedNavHostaction_innerFragmentB1_to_innerFragmentB2导航到B1(发生在B2上)
  4. 按下(embeddedNavHostembeddedNavHost返回到B2 [期望结果])
  5. 按下(B1navHost返回到B [期望结果])
  6. 再次通过A导航到action_fragmentA_to_fragmentB
  7. B [不期望的结果]

所以最后,我最终做了:

IllegalArgumentException: navigation destination id/action_fragmentA_to_fragmentB

这最终成功了。没有崩溃。但是,我只是想是否有一种更正确/自动的方法来处理嵌入式override fun onSupportNavigateUp(): Boolean { val hostedFragment = navHost?.childFragmentManager?.primaryNavigationFragment return when(hostedFragment){ is FragmentB -> { if(hostedFragment.isInnerFragmentB2Showing()){ findNavController(R.id.embeddedNavHostFragment).navigateUp() } else { findNavController(R.id.navHost).navigateUp() } } is FragmentA -> { findNavController(R.id.navHost).navigateUp() } else -> false } } 的向上导航。当前的方法感觉更像是一种解决方法,而不是适当的解决方案。还有其他替代方法来使它起作用吗?

此外,我很好奇人们对NavHostFragments观点相互嵌入。这是适当的用途吗?弄清楚如何相应地处理后退按钮不是一个简单或直接的解决方案,因为没有关于将NavHostFragments彼此嵌入并在父片段和子片段之间来回导航的文档。因此,我想知道是否没有文档的原因是因为它可能是对NavigationComponent的不正确(或意外)使用,因此被推荐。

如果您想看看我的示例项目,请转到here

0 个答案:

没有答案