Home » Android » android – How to switch to other fragment in different back stack using Navigation Component?

android – How to switch to other fragment in different back stack using Navigation Component?

Posted by: admin June 15, 2020 Leave a comment

Questions:

I have 3 bottom navigation tabs called Home, Dashboard, Profile.

  • In Home, I have Fragment1 and Fragment2,
  • In Dashboard, I have Fragment3 and Fragment4
  • And in Profile, I have MyProfile and EditProfile.

Now, in Fragment2, a button changeAvatar can open EditProfile in stack Profile. Because EditProfile should be in tab Profile, so if I don’t want to include EditProfile into navGraph of Home, how can I achieve that behavior?

How to&Answers:

try with the deep link

Navigation graph.

<navigation
 ...>
    <fragment
        android:id="@+id/editProfileFragment"
        >

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

In Fragment.

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

Answer:

You have to declare your action like this for getting a fragment from your back stack

<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" />

Answer:

What you are looking for is known as global action.

Given you have the following nav_graph structure:

<?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>

Note the action section within actionProfile:

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

The above is the actual global action that you are looking for.

So to put the flow into perspective you would do the following to navigate from Fragment2 changeAvatar button.

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

Answer:

To navigate from Home > Fragment2 to Profile > EditProfile you can pass an id by edit type using Navigation.

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");
}

Note: The arguments of a navigation cannot be of type Enum

GL