Navigation from a destination to another destination in another navigation graph in Android Kotlin
Asked Answered
H

2

3

I'm new at navigation graph and I have a simple movie application that contains a BottomNavigationView with 2 tabs or 2 icons , the first icon or first tab contains 2 Fragments the first one is FeedFragment and I navigate from it to DetailsFragment and I put these 2 Fragment in nested graph . The second tab for FavoritFragment .

Below my code in nav_graph.xml

<?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/my_nav"
    app:startDestination="@id/homeNavigation">


    <fragment
        android:id="@+id/favoritesFragment"
        android:name="com.tito.movieapps.ui.fragments.FavoritesFragment"
        android:label="@string/favorites"
        tools:layout="@layout/fragment_favorites" >

        <action
            android:id="@+id/action_favoritesFragment_to_homeNavigation"
            app:destination="@id/detailsFragment" />
    </fragment>
    <navigation
        android:id="@+id/homeNavigation"
        android:label="Home nested graph"
        app:startDestination="@id/feedFragment">
        <fragment
            android:id="@+id/feedFragment"
            android:name="com.tito.movieapps.ui.fragments.FeedFragment"
            android:label="@string/feed_page"
            tools:layout="@layout/fragment_feed">
            <action
                android:id="@+id/action_feedFragment_to_detailsFragment"
                app:destination="@id/detailsFragment" />

        </fragment>
        <fragment
            android:id="@+id/detailsFragment"
            android:name="com.tito.movieapps.ui.fragments.DetailsFragment"
            android:label="Details"
            tools:layout="@layout/fragment_details">
            <argument
                android:name="movieItem"
                app:argType="com.tito.domain.entites.MovieModelItem" />
        </fragment>
    </navigation>

</navigation>

I can navigate from FeedFragment to DetailsFragment and I pass a Parcelable object . I want to navigate from FavoriteFragment to DetailsFragment (in the nested navigationGraph) and when I write the below code in FavoriteFragment

lifecycleScope.launchWhenStarted {
            detailsViewModel.getSavedMovie().collectLatest { movies->
               if(movies.isNotEmpty()) {
                   favoritesAdapter = FavoritesAdapter(object : FavoritesAdapter.OnItemClick{
                       override fun onItemClick(movieModelItem: MovieModelItem) {

                           val id = FavoritesFragmentDirections.actionFavoritesFragmentToHomeNavigation(movieModelItem)

                            findNavController().navigate(id)
                       }
                   })
                   binding.movieRec.adapter = favoritesAdapter
                   favoritesAdapter.differ.submitList(movies)
               }else{
                   Toast.makeText(requireActivity(),"No data",Toast.LENGTH_LONG).show()
               }
            }
        }

And run the app , I can't run it I get the below error

e: D:\MovieApps\app\src\main\java\com\tito\movieapps\ui\fragments\FavoritesFragment.kt: (48, 105): Too many arguments for public final fun actionFavoritesFragmentToHomeNavigation(): NavDirections defined in com.tito.movieapps.ui.fragments.FavoritesFragmentDirections.Companion

I can't fix this error so please help me

Haricot answered 5/7, 2023 at 17:49 Comment(4)
https://mcmap.net/q/678613/-navigate-between-different-graphs-with-navigation-components/6576302Interstate
I already added the second navigation graph in the nav_graph.xml . And when I make an action from Favorite to the Home graph , it navigate to the Home no the Details screenHaricot
try to not pass any data, and test that without "movieModelItem". And see what will happen.Interstate
I changed the action to make it navigate to the homeGraph and in navigated to the FeedFragment which is the start destination of the homeGrapgh , but I need to navigate to Favorite Fragment which is the the second destination in the homeGraph , and when I change the action and make the destination to FavoriteFragment, it needs to pass to it the argument which is in the FavoritFragment .Haricot
H
0

I found the solution , thanks to Chat OpenAI

If I want to navigate from a fragment to another destination in another navigation graph we should do the following

1- Navigate from the destination(Favorite Fragment) to the other navigation graph (Home Navigation Graph)

 <fragment
        android:id="@+id/favoritesFragment"
        android:name="com.tito.movieapps.ui.fragments.FavoritesFragment"
        android:label="@string/favorites"
        tools:layout="@layout/fragment_favorites" >
        <action
            android:id="@+id/action_favoritesFragment_to_homeNavigation4"
            app:destination="@id/homeNavigation" />

Then we make an action from the start destination (FeedFragment) in the Home Navigation Graph graph to the DetailsFragment like the code below

<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/my_nav"
    app:startDestination="@id/homeNavigation">


    <fragment
        android:id="@+id/favoritesFragment"
        android:name="com.tito.movieapps.ui.fragments.FavoritesFragment"
        android:label="@string/favorites"
        tools:layout="@layout/fragment_favorites" >
        <action
            android:id="@+id/action_favoritesFragment_to_homeNavigation4"
            app:destination="@id/homeNavigation" />
    </fragment>
    <navigation
        android:id="@+id/homeNavigation"
        android:label="Home nested graph"
        app:startDestination="@id/feedFragment">
        <fragment
            android:id="@+id/feedFragment"
            android:name="com.tito.movieapps.ui.fragments.FeedFragment"
            android:label="@string/feed_page"
            tools:layout="@layout/fragment_feed">
            <action
                android:id="@+id/action_feedFragment_to_detailsFragment"
                app:destination="@id/detailsFragment" />

        </fragment>
        <fragment
            android:id="@+id/detailsFragment"
            android:name="com.tito.movieapps.ui.fragments.DetailsFragment"
            android:label="Details"
            tools:layout="@layout/fragment_details">
            <argument
                android:name="movieItem"
                app:argType="com.tito.domain.entites.MovieModelItem" />
        </fragment>
    </navigation>

</navigation>

Then in the FavoriteFragment in OnItemClick

  val id  = FavoritesFragmentDirections.actionFavoritesFragmentToHomeNavigation4()
                               findNavController().navigate(id)
                               val args = DetailsFragmentArgs(movieModelItem)
                               findNavController().navigate(R.id.action_feedFragment_to_detailsFragment,args.toBundle())
Haricot answered 15/7, 2023 at 21:22 Comment(0)
I
0

I am not aware of full code of your project, so, I just can suggest a trick (that is a non-standard and temporary solution).

Add an Boolean argument e.g. shouldIGo and an Nullable variable movieItemData into your homeNavigation. My trick goes like this, if someone entered into this homeNavigation with ShouldIGo == true (and of course in this case movieItemData must be Non-null and attached to the direction) then automatically navigate to DetailsFragment with that extra data.

<navigation
    android:id="@+id/homeNavigation"
    android:label="Home nested graph"
    app:startDestination="@id/feedFragment">
    <fragment
        android:id="@+id/feedFragment"
        android:name="com.tito.movieapps.ui.fragments.FeedFragment"
        android:label="@string/feed_page"
        tools:layout="@layout/fragment_feed">
        <action
            android:id="@+id/action_feedFragment_to_detailsFragment"
            app:destination="@id/detailsFragment" />

        <argument <!-- this has been added -->
            android:name="movieItemData"
            app:argType="com.tito.domain.entites.MovieModelItem"
            android:defaultValue="@null"
            app:nullable="true"/>
        <argument <!-- this has been added -->
            android:name="shouldIGo"
            app:argType="boolean"
            android:defaultValue="false"/>

    </fragment>
    <fragment
        android:id="@+id/detailsFragment"
        android:name="com.tito.movieapps.ui.fragments.DetailsFragment"
        android:label="Details"
        tools:layout="@layout/fragment_details">
        <argument
            android:name="movieItem"
            app:argType="com.tito.domain.entites.MovieModelItem" />
    </fragment>
</navigation>

And in home fragment of homeNavigation, i.e. FeedFragment check that if shouldIGo is true or not. if it was true then navigate to detailsFragment.

private FeedFragmentArgs args;

...

onCreate ... 

args = FeedFragmentArgs.fromBundle(requireArguments());

if (args.shouldIGo == true) {
//navigate to detailsFragment with movieItemData data.
}
Interstate answered 15/7, 2023 at 16:15 Comment(12)
What is the destination from the Favorite Fragment ? I made it HomeNavigation but it doesn't accept any params even I added the 2 argument in FeedFragment . Or should I make the destination to FeedFragment ?Haricot
As you have defined it by action_favoritesFragment_to_homeNavigation the destination is home fragment of homeNavigation.Interstate
Do you know how to play with navgraph in android studio? every thing is in right side panel. arguments, directions, etc.Interstate
Yes I have added the 2 argument in FeedFragment and I have added an action from FavoriteFragment to HomeNavigation like the below code <fragment android:id="@+id/favoritesFragment" android:name="com.tito.movieapps.ui.fragments.FavoritesFragment" android:label="@string/favorites" tools:layout="@layout/fragment_favorites" > <action android:id="@+id/action_favoritesFragment_to_homeNavigation3" app:destination="@id/homeNavigation" /> </fragment> But I can't add parameters in the actionHaricot
Parameters that I have defined is for homeNavigation. If someone (A) want to enter in homeNavigation he (A) must show his boolean key to allow to enter. this is like a lock and key. lock is in destination always and key is in hand of who wants to enter.Interstate
So If you want to use my trick, and travel from favorites to homeNavigation, in codes (not in graph) you should pass that boolean.Interstate
Could you edit your answer and show me how the action will be in Favorite Fragment ?Haricot
What you commented in above is ok. nothing else is needed in NavGraph.Interstate
But it doesn't need an arguments when I use the action in FavoritFragment val id = FavoritesFragmentDirections.actionFavoritesFragmentToHomeNavigation3() findNavController().navigate(id)Haricot
Android studio will help you if it needs any argument, in this case it needs. Add a dot at the end of FavoritesFragmentDirections.actionFavoritesFragmentToHomeNavigation3() and see what it needs?Interstate
I should pass the arguments in the action not after it , it will not accept params cause the destination is HomeNavigation not FeedFragmentHaricot
In java, if there are two arguments then it should pass after parenthesis. But I am not sure,Interstate
H
0

I found the solution , thanks to Chat OpenAI

If I want to navigate from a fragment to another destination in another navigation graph we should do the following

1- Navigate from the destination(Favorite Fragment) to the other navigation graph (Home Navigation Graph)

 <fragment
        android:id="@+id/favoritesFragment"
        android:name="com.tito.movieapps.ui.fragments.FavoritesFragment"
        android:label="@string/favorites"
        tools:layout="@layout/fragment_favorites" >
        <action
            android:id="@+id/action_favoritesFragment_to_homeNavigation4"
            app:destination="@id/homeNavigation" />

Then we make an action from the start destination (FeedFragment) in the Home Navigation Graph graph to the DetailsFragment like the code below

<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/my_nav"
    app:startDestination="@id/homeNavigation">


    <fragment
        android:id="@+id/favoritesFragment"
        android:name="com.tito.movieapps.ui.fragments.FavoritesFragment"
        android:label="@string/favorites"
        tools:layout="@layout/fragment_favorites" >
        <action
            android:id="@+id/action_favoritesFragment_to_homeNavigation4"
            app:destination="@id/homeNavigation" />
    </fragment>
    <navigation
        android:id="@+id/homeNavigation"
        android:label="Home nested graph"
        app:startDestination="@id/feedFragment">
        <fragment
            android:id="@+id/feedFragment"
            android:name="com.tito.movieapps.ui.fragments.FeedFragment"
            android:label="@string/feed_page"
            tools:layout="@layout/fragment_feed">
            <action
                android:id="@+id/action_feedFragment_to_detailsFragment"
                app:destination="@id/detailsFragment" />

        </fragment>
        <fragment
            android:id="@+id/detailsFragment"
            android:name="com.tito.movieapps.ui.fragments.DetailsFragment"
            android:label="Details"
            tools:layout="@layout/fragment_details">
            <argument
                android:name="movieItem"
                app:argType="com.tito.domain.entites.MovieModelItem" />
        </fragment>
    </navigation>

</navigation>

Then in the FavoriteFragment in OnItemClick

  val id  = FavoritesFragmentDirections.actionFavoritesFragmentToHomeNavigation4()
                               findNavController().navigate(id)
                               val args = DetailsFragmentArgs(movieModelItem)
                               findNavController().navigate(R.id.action_feedFragment_to_detailsFragment,args.toBundle())
Haricot answered 15/7, 2023 at 21:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.