【问题标题】:How to switch to other fragment in different back stack using Navigation Component?如何使用导航组件切换到不同后台堆栈中的其他片段?
【发布时间】:2020-04-29 09:09:05
【问题描述】:

我有 3 个底部导航选项卡,名为 Home, Dashboard, Profile

  • Home,我有Fragment1Fragment2
  • Dashboard,我有Fragment3Fragment4
  • Profile 中,我有MyProfileEditProfile

现在,在Fragment2 中,一个按钮changeAvatar 可以在堆栈Profile 中打开EditProfile。因为EditProfile 应该在标签Profile 中,所以如果我不想将EditProfile 包含在HomenavGraph 中,我该如何实现这种行为?

【问题讨论】:

  • 我无法理解,您希望在导航 A 或 C 中加载片段 6?
  • @notTdar 抱歉,我进行了编辑以提高可读性。
  • 你有 3 个 nav_graphs 吗?为什么不使用 1 个 Activity 和 1 个 nav_graph,其中所有 6 个片段都作为可能的目的地?
  • @muetzenflo 是的,完全使用与 NavigationAdvanceSample 相同的 3 个 nav_graphs。如果我使用 BottomNavigationView ,如何使用 1 nav_graph ?当我回来时,每个堆栈都应该保留它的顶部片段。
  • 啊,我明白了。没有得到这个要求。对不起,另一个问题:你为什么不想在 Home-nav_graph 中使用 EditProfile。如果您使用 Jetpack 的 ViewModel 方法,则使用 E​​ditProfile 作为Home 中的“第三个”导航目的地应该没有问题。如果 BottomNavigation 是包含 navHostFragment 的活动的一部分,则可以使用 1 个 nav_graph。

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


【解决方案1】:

您要查找的内容称为global action

假设你有以下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/main_nav_graph"
            app:startDestination="@id/actionHome">

    <navigation
            android:id="@+id/actionHome"
            android:label="Home"
            app:startDestination="@id/fragment1">
        <fragment
                android:id="@+id/fragment1"
                android:name="com.example.app.Fragment1"
                android:label="Home Fragment 1"
                tools:layout="@layout/fragment_1" />
        <fragment
                android:id="@+id/fragment2"
                android:name="com.example.app.Fragment2"
                android:label="Home Fragment 2"
                tools:layout="@layout/fragment_2" />

    </navigation>

    <navigation
            android:id="@+id/actionDashboard"
            android:label="Dashboard"
            app:startDestination="@id/fragment3">
        <fragment
                android:id="@+id/fragment3"
                android:name="com.example.app.Fragment3"
                android:label="Dashboard Fragment 3"
                tools:layout="@layout/fragment_3" />
        <fragment
                android:id="@+id/fragment4"
                android:name="com.example.app.Fragment4"
                android:label="Dashboard Fragment 4"
                tools:layout="@layout/fragment_4" />

    </navigation>

    <navigation
            android:id="@+id/actionProfile"
            android:label="Profile"
            app:startDestination="@id/myProfileFragment">
        <fragment
                android:id="@+id/myProfileFragment"
                android:name="com.example.app.MyProfileFragment"
                android:label="My Profile"
                tools:layout="@layout/fragment_my_profile"/>

        <fragment
                android:id="@+id/editProfileFragment"
                android:name="com.example.app.EditProfileFragment"
                android:label="Edit Profile"
                tools:layout="@layout/fragment_edit_profile"/>

        <action
                android:id="@+id/navigateToEditProfile"
                app:destination="@id/editProfileFragment" />
    </navigation>
</navigation>

注意actionProfile中的action部分:

<action
        android:id="@+id/navigateToEditProfile"
        app:destination="@id/editProfileFragment" />

以上是您正在寻找的实际全局操作

因此,要透视流程,您将执行以下操作以从 Fragment2changeAvatar 按钮导航。

fun navigateToChangeAvatar() {
    changeAvatar.setOnClickListener { view ->
        view.findNavController().navigate(R.id.navigateToEditProfile)
    }
}

【讨论】:

    【解决方案2】:

    尝试使用深层链接

    导航图。

    <navigation
     ...>
        <fragment
            android:id="@+id/editProfileFragment"
            >
    
            ...
            <deepLink
                android:id="@+id/deepLink"
                app:uri="yourapp://edit/prfile" />
            ...
        </fragment>
    </navigation>
    

    在片段中。

    findNavController().navigate(Uri.parse("yourapp://edit/prfile"))
    

    【讨论】:

    • 你试过这个,堆栈发生了什么?你能分享更多关于这个解决方案的信息吗?
    【解决方案3】:

    您必须像这样声明您的操作才能从您的后台堆栈中获取片段

    <action
        android:id="@+id/yourActionName"
                     app:destination="@id/editProfileFragment" />
                     app:enterAnim="@anim/slide_in_right"
                     app:exitAnim="@anim/slide_out_left"
                     app:popEnterAnim="@anim/slide_in_left"
                     app:popExitAnim="@anim/slide_out_right"
                     app:popUpTo="@+id/editProfileFragment" />
    

    【讨论】:

      【解决方案4】:

      要从 Home > Fragment2 导航到 Profile > EditProfile,您可以使用 Navigation 按编辑类型传递 id。

      Fragment2.kt

      private fun navigateToEditProfileAvatar() {
          buttonEditProfileAvatar.setOnClickListener { button -> 
              Navigation.findNavController(button).navigate(
                      R.id.action_global_to_edit_profile,
                      RootNavigationDirections.actionGlobalToEditProfile(
                              editType = EditType.EDIT_PROFILE_AVATAR.id
                      ).arguments
              )
          }
      }
      

      EditProfileFragment.kt

      override fun onActivityCreated(savedInstanceState: Bundle?) {
          super.onActivityCreated(savedInstanceState) 
      
          ...
      
          viewModel.setEditTypeId(EditProfileFragmentArgs.fromBundle(arguments ?: Bundle()).editType)
      
      }
      
      private fun bind() {
          when (viewModel.editTypeId) {
               EditType.EDIT_PROFILE.id -> { ... }
               EditType.EDIT_PROFILE_AVATAR.id -> { 
                   // here
               }
          }
      }
      

      EditProfileVM.kt

      val editTypeId = MutableLiveData<String>()
      fun setEditTypeId(id: editTypeId ) {...}
      

      res/navigation/root_navigation.xml

      <action
          android:id="@+id/action_global_to_edit_profile"
          app:destination="@id/edit_profile_fragment" />
      
      <fragment
          android:id="@+id/edit_profile_fragment"
          android:name="EditProfileFragment"
          android:label=" "
          tools:layout="@layout/fragment_edit_profile">
      
          <argument
              android:name="editType"
              app:argType="string"
              android:defaultValue="@string/edit_profile"
          />
      
      </fragment>
      

      EditType.kt

      enum class EditType(val id: String) {
          EDIT_PROFILE("EDIT_PROFILE"), EDIT_PROFILE_AVATAR("EDIT_PROFILE_AVATAR");
      }
      

      注意:导航的参数不能是枚举类型

      GL

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多