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?
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"))
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" />
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)
}
}
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