I have tried multiple ways to achieve navigation
Have a look at this class and for full source See this
activity_main.xml
Android studio recommend FragmentContainerView to be used for Navigation purpose. I simply want to show two fragments one is the PhotosFragment and the other is PhotoDetailFragment using Navigation component.
nav_graph.xml
<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/photosFragment">
<fragment android:id="#+id/photosFragment"
android:name="gallery.app.architecture.ui.photos.PhotosFragment"
tools:layout="#layout/item_photo">
<action android:id="#+id/action_photosFragment_to_photoDetailFragment"
app:destination="#id/photoDetailFragment" app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left" app:popEnterAnim="#anim/slide_in_left"
app:popExitAnim="#anim/slide_out_right"/>
</fragment>
<fragment android:id="#+id/photoDetailFragment"
android:name="gallery.app.architecture.ui.photos.PhotoDetailFragment"
tools:layout="#layout/item_photo">
<argument android:name="imageUrl" app:argType="string"/>
<argument android:name="userName" app:argType="string"/>
<argument android:name="tags" app:argType="string"/>
</fragment>
</navigation>
I simply want to show two fragment one with PhotosFragment(List of photos) and on Click on any photo . Move to PhotoDetailFragment.
Latest code is pushed to Github along with it's link share above.When I test fragment individually, it's working correct. but navigation component not working as it should be.
Issue Resolved
MainActivity with Navigation doesn't work with binding.
Related
I am facing an issue with bottom navigation when navigating through different fragments,
There are 3 fragments as follows:
List, Loading & Playing
When user taps on Lists, it has to go to loading and if everything goes well when loading, it moves to Playing fragment. I'm using app:popUpTo="#id/loadingFragment" app:popUpToInclusive="true" so it doesn't show when I come back from Playing to List fragment.
The main problem is, whenever I click on any item from Listing after the first cycle(as mentioned above), it opens the Playing fragment directly and it doesn't show the intermediate loading fragment
<fragment
android:id="#+id/loadingFragment"
tools:layout="#layout/fragment_loading">
<argument
android:name="object_id"
app:argType="string" />
<argument
android:name="object_name"
app:argType="string" />
<action
android:id="#+id/loadingToPlaying"
app:destination="#id/playingFragment"
app:popUpTo="#id/loadingFragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/playingFragment"
tools:layout="#layout/fragment_playing">
<argument
android:name="session_object_id"
app:argType="string" />
<argument
android:name="session_name"
app:argType="string" />
</fragment>
I am using the single activity approach with the navigation component. I have the main activity which is a container for the main fragment. The main fragment contains a container for all other fragments in the app and the bottom navigation. I've created several graphs to allow each tab to own its own navigation back stack. The main problem I don't know how to add the ability to open a modal graph by the deep link. By clicking on the deep link, should be opened an info fragment, and clicking the back button should be shown the previous one not depending on the tab. For example, I have 4 tabs: home, search, tools, and account. If the search was opened, and the screen by deep link was shown, by clicking the back button search or any of its nested fragments should be opened. For now, in any case, the account tab will be opened because the deep link flow belongs to its nav graph. Here is the navigation code:
The app navigation for activity:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/nav_graph"
app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.app.flow.main.MainFragment"
android:label="MainFragment">
<deepLink app:uri="------/password/edit" />
<deepLink app:uri="------/confirmation" />
</fragment>
The main fragment navigation 1 graph per tab:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_nav_graph"
app:startDestination="#id/home_graph">
<include app:graph="#navigation/home_graph" />
<include app:graph="#navigation/search_graph" />
<include app:graph="#navigation/tools_graph" />
<include app:graph="#navigation/account_graph" />
</navigation>
And the part of the account graph which is responsible for deep link flow:
<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/account_graph"
app:startDestination="#id/accountFragment">
***************************
<fragment
android:id="#+id/checkLinkFragment"
android:name="com.app.flow.checklink.CheckLinkFragment"
android:label="CheckLinkFragment">
<deepLink app:uri="-----/confirmation" />
<action
android:id="#+id/action_checkLinkFragment_to_emailConfirmedFragment"
app:destination="#id/emailConfirmedFragment" />
<action
android:id="#+id/action_checkLinkFragment_to_confirmationExpiredFragment"
app:destination="#id/confirmationExpiredFragment" />
</fragment>
***********************
</navigation>
I am using the navigation architecture component in my app and whenever I navigate to a screen and then try to return to the previous screen using the back button, instead of navigating back the app exits.
My Navigation Graph looks like this:
<?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_host_fragment"
app:startDestination="#id/authFragment">
<fragment
tools:layout="#layout/fragment_main_screen"
android:id="#+id/sellerListScreenFragment"
android:name="com.example.paylater.ui.SellerMainScreenFragment"
android:label="SellerListScreenFragment" >
<action
android:id="#+id/action_sellerListScreenFragment_to_creditFragment"
app:destination="#id/credit_nav_graph" />
</fragment>
<fragment
android:id="#+id/authFragment"
android:name="com.example.paylater.ui.AuthFragment"
android:label="AuthFragment"
tools:layout="#layout/fragment_auth" >
<action
android:id="#+id/action_authFragment_to_sellerListScreenFragment"
app:destination="#id/sellerListScreenFragment" />
</fragment>
<navigation android:id="#+id/credit_nav_graph"
app:startDestination="#id/creditFragment">
<fragment
android:id="#+id/creditAddFragment"
android:name="com.example.paylater.ui.CreditAddFragment"
android:label="CreditAddFragment"
tools:layout="#layout/fragment_credit_add">
<action
android:id="#+id/action_creditAddFragment_self"
app:destination="#id/creditAddFragment" />
<action
android:id="#+id/action_creditAddFragment_to_transactionResultFragment"
app:destination="#id/transactionResultFragment" />
</fragment>
<fragment
android:id="#+id/transactionResultFragment"
android:name="com.example.paylater.ui.TransactionResultFragment"
android:label="TransactionResultFragment"
tools:layout="#layout/fragment_transaction_result">
<action
android:id="#+id/action_transactionResultFragment_self"
app:destination="#id/transactionResultFragment" />
</fragment>
<fragment
android:id="#+id/creditFragment"
android:name="com.example.paylater.ui.CreditFragment"
android:label="CreditFragment"
tools:layout="#layout/fragment_credit_enter_no">
<action
android:id="#+id/action_creditFragment_to_creditAddFragment"
app:destination="#id/creditAddFragment" />
<action
android:id="#+id/action_creditFragment_self"
app:destination="#id/creditFragment" />
</fragment>
</navigation>
<action android:id="#+id/action_global_sellerListScreenFragment" app:destination="#id/sellerListScreenFragment"/>
</navigation>
I've tried to fix this using a custom onBackPressedDispatcher callback, but on top of leading to some strange behaviour it is also tedious to do it for every fragment and seems to be too much work for something that should be handled by the navigation component.
So is there a way to fix this problem as I have gone through my code but there doesn't seem to be anything that influences the navigation behaviour yet it doesn't work as intended.
Thanks for helping out!
Edit :-
As asked, I am providing the setup using which I navigate from , for example, SellerMainScreenFragment to CreditFragment
binding.fabCredit.setOnClickListener {
findNavController().
navigate(R.id.action_sellerListScreenFragment_to_creditFragment)
}
Here I use a FAB to navigate from SellerMainScreenFragment to CreditFragment.
But after navigating to CreditFragment, on pressing the back button the app just exits instead of navigating back.
I think you forgot to add app:defaultNavHost="true" to the NavHostFragment in your main Activity layout:
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
From the documentation:
The app:defaultNavHost="true" attribute ensures that your NavHostFragment intercepts the system Back button. Note that only one NavHost can be the default. If you have multiple hosts in the same layout (two-pane layouts, for example), be sure to specify only one default NavHost.
https://developer.android.com/guide/navigation/navigation-getting-started
So I was using Jetpack navigation and the number of fragments kept growing up.
We can separate fragments in different navigation graph as described in this document
jetpack nav graph docs
Then I tried to put different nav graphs in different files because that felt more organized and readable file but I get the following error when I try to navigate to different nav_graph files.
nav_graph_start.xml
<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_start"
app:startDestination="#id/splashScreen"
tools:ignore="UnusedNavigation">
<fragment
android:id="#+id/splashScreen"
android:name="com.timetoface.android.splash.SplashFragment"
android:label="Login Fragment"
tools:layout="#layout/fragment_splash">
<action
android:id="#+id/action_splash_to_login"
app:destination="#id/nav_graph_auth"
/>
<action
android:id="#+id/action_splash_to_home"
app:destination="#id/nav_graph_home"
/>
</fragment>
</navigation>
nav_graph_auth.xml
<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_auth"
app:startDestination="#id/emailLoginScreen"
tools:ignore="UnusedNavigation">
................................
</navigation>
nav_graph_home.xml
<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_home"
app:startDestination="#id/emailLoginScreen"
tools:ignore="UnusedNavigation">
................................
</navigation>
navigation destination com.app.android:id/nav_graph_home
referenced from action com.app.android:id/action_splash_to_home
is unknown to this NavController
So,
Are multiple navigation graph files not supported yet?
Am I missing something that I should change?
First of all you can use include. Take a look this
example: first_graph.xml
<include app:graph="#navigation/second_graph" />
then set action to included graph's id
<action
android:id="#+id/action_fragment_to_second_graph"
app:destination="#id/second_graph" />
Also you can use extension to use multiple graphs merged.
Take a look to this
Actually every activity should have it's own nav graph.
Ofcourse you can have multiple nav graph in your application. Each Activity can have only one Navigation Graph. I just added two Nav_Graph for different activity. Works fine. Here is a screenshot of my Navigation folder.
While using navigation architecture as from here , here clearTask is deprecated.
My scenario is this: There are 2 screens Login and Registration, both have links to each other. So you can go to Registration from Login and also Login from Registration. But on back Press App should be closed.
It could simply be done by just adding clearTask to both actions as below.
<?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/nv_auth_phase"
app:startDestination="#id/fragment_login">
<fragment
android:id="#+id/fragment_login"
android:name="com.jobhook.ui.auth.login.LoginFragment"
android:label="LoginFragment"
tools:layout="#layout/fragment_login">
<action
android:id="#+id/nv_action_login_to_registration"
app:clearTask="true"
app:destination="#id/fragment_registration" />
</fragment>
<fragment
android:id="#+id/fragment_registration"
android:name="com.jobhook.ui.auth.registration.RegistrationFragment"
android:label="RegistrationFragment"
tools:layout="#layout/fragment_registration">
<action
android:id="#+id/nv_action_registration_to_login"
app:clearTask="true"
app:destination="#id/fragment_login" />
</fragment>
</navigation>
But as it was deprecated I have tried other solution like adding popUpTo -> navigation graph's Id, making launchSingleTop to true in both actions. Nothing seems to work in my scenario.
I have checked this question also but didn't get a solution.
You need to use in your action next code
app:popUpTo="#+id/fragment_login"
app:popUpToInclusive="true"
Set your NavHostFragment defaultNavHost value false,
<fragment
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="false"
app:navGraph="#navigation/nav_graph"
... />
The app:defaultNavHost="true" attribute ensures that your NavHostFragment intercepts the system Back button. Note that only one NavHost can be the default. If you have multiple hosts in the same layout (two-pane layouts, for example), be sure to specify only one default NavHost.
Simple and effective solution:
fun signOut(activity: Activity) = activity.finish()