Android Navigation Component (State retained) - android

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>

Related

Android navigation component open a modal graph by deep link

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>

Android Navigation Component: Issues with animations and backstack when returning to prior fragment via direction

Here's my scenario, boiled down as much as possible:
I have 2 fragments, A and B. There's a circular path between A and B on the graph, so A has a button that navigates to B, and B has a button to navigate to A. I'm having two issues with this scenario.
I'm playing an animation (a simple modal "slide up" where B slides up ontop of A) when launching B. It plays fine forwards (launching B) and back (pressing back). I would like it to play the exit animation when I navigate back to A as well (same animation as if I had pressed the back button, but on the fragment transaction). I can get an enter animation to play on A, but no exit animation will play on B.
The backstack. When navigating back to A, I don't want B or the first instance of A to remain on the backstack.
I've put together a sample project that demonstrates this issue: https://github.com/Morrodin/animtest
I'll include my graph directly in this post as well:
<?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/nav_graph"
app:startDestination="#id/FirstFragment">
<fragment
android:id="#+id/FirstFragment"
android:name="com.example.myapplication.FirstFragment"
android:label="#string/first_fragment_label"
tools:layout="#layout/fragment_first">
<action
android:id="#+id/action_FirstFragment_to_SecondFragment"
app:destination="#id/SecondFragment"
app:enterAnim="#anim/slide_in_up"
app:exitAnim="#anim/none"
app:popEnterAnim="#anim/none"
app:popExitAnim="#anim/slide_out_down" />
</fragment>
<fragment
android:id="#+id/SecondFragment"
android:name="com.example.myapplication.SecondFragment"
android:label="#string/second_fragment_label"
tools:layout="#layout/fragment_second">
<action
android:id="#+id/action_SecondFragment_to_FirstFragment"
app:destination="#id/FirstFragment"
app:enterAnim="#anim/none"
app:exitAnim="#anim/slide_out_down"
app:popEnterAnim="#anim/none"
app:popExitAnim="#anim/slide_out_down" />
</fragment>
</navigation>

Is it possible to move the screen without connecting in nav_graph?

I am using BottomNavigation.
The transition from the screen of menu A to another screen, not the screen transition from menu A to another, is as follows.
menu A(fragment) -> B screen(fragment) -> C screen(fragment) -> B screen(fragment)
I hooked up these screen transitions in nav_graph
I am using BottomNavigation.
The transition from the screen of menu A to another screen, not the screen transition from menu A to another, is as follows.
menu A(fragment) -> B screen(fragment) -> C screen(fragment) -> D screen(fragment)
I hooked up these screen transitions in nav_graph
However, the screen transition from D to C was not connected, but it was possible to switch the screen using view.findNavController.navigate().
I thought transitioning the screen was impossible without connecting to the nav_graph.
How is this possible?
UPDATED
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/nav_graph"
app:startDestination="#id/calendar">
<fragment
android:id="#+id/calendar"
android:name="com.example.writeweight.fragment.CalendarFragment"
android:label="fragment_calendar"
tools:layout="#layout/fragment_calendar" >
</fragment>
<fragment
android:id="#+id/list"
android:name="com.example.writeweight.fragment.WorkoutListFragment"
android:label="fragment_workout_list"
tools:layout="#layout/fragment_workout_list" />
<!-- menu A fragment -->
<fragment
android:id="#+id/write_home"
android:name="com.example.writeweight.fragment.WriteRoutineHomeFragment"
android:label="fragment_write_routine_home"
tools:layout="#layout/fragment_write_routine_home" >
<action
android:id="#+id/action_write_home_to_bodyPartDialog"
app:destination="#id/bodyPartDialog" />
</fragment>
<!-- B screen -->
<dialog
android:id="#+id/bodyPartDialog"
android:name="com.example.writeweight.fragment.BodyPartDialogFragment"
android:label="BodyPartDialogFragment"
tools:layout="#layout/fragment_body_part_dialog">
<action
android:id="#+id/action_bodyPartDialog_to_write"
app:destination="#id/write"/>
</dialog>
<!-- C screen -->
<fragment
android:id="#+id/write"
android:name="com.example.writeweight.fragment.WritingRoutineFragment"
android:label="WritingRoutineFragment"
tools:layout="#layout/fragment_writing_routine">
<action
android:id="#+id/action_write_to_bodyPartDialog"
app:destination="#id/bodyPartDialog" />
<argument
android:name="title"
app:argType="string"
android:defaultValue="" />
</fragment>
<!-- D screen -->
<fragment
android:id="#+id/workoutListTabFragment"
android:name="com.example.writeweight.fragment.WorkoutListTabFragment"
android:label="fragment_workout_list_tab"
tools:layout="#layout/fragment_workout_list_tab" />
</navigation>
As per the Navigate using ID documentation:
navigate(int) takes the resource ID of either an action or a destination.
So both directly navigating to any destination is possible (by using the ID of the destination) and navigating via an action is supported.
The documentation goes on to say:
Note: When navigating using IDs, we strongly recommend using actions where possible. Actions provide additional information in your navigation graph, visually showing how your destinations connect to each other. By creating actions, you can replace resource IDs with Safe Args-generated operations, providing additional compile-time safety. By using an action, you can also animate transitions between the destinations. For more information, see Animate transitions between destinations.

Navigation Component not working with FragmentContainerView

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.

Pressing back button exits the app instead of navigating to the previous screen while using navigation component

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

Categories

Resources