Android Exit sub nav graph - android

I am using one nav_graph and I have a scenario like I have fragment1 and going to other fragment which is a sub nav graph and it has a couple of
fragments(fragment3 and fragment4) and start destination is fragment3 and from fragment3 I am going to fragment4 and fragment4 has "DONE" button.
Here is the scenario:
I am calling this sub nav graph from fragment1 and from fragment4 I want to redirect to it is parent i.e fragment1
I am calling this sub nav graph from fragment2 and from fragment4 I want to redirect to it is parent i.e fragment2
This is how I am handling the done button click event inside fragment4:
findNavController().currentDestination?.parent?.startDestination?.let {
findNavController().popBackStack(it, true)
}
But it is not redirecting to parent it is redirecting to the subgraph stat destination i.e fragment3
Here is how my nav_graph is looking:
Here are two fragments:
<fragment
android:id="#+id/fragment1"
android:name="fragment1"
android:label="fragment1">
<action
android:id="#+id/action_fragment1_to_sub_graph"
app:destination="#id/sub_graph_id" />
</fragment>
<fragment
android:id="#+id/fragment2"
android:name="fragment2"
android:label="fragment2">
<action
android:id="#+id/action_fragment2_to_sub_graph"
app:destination="#id/sub_graph_id" />
</fragment>
Here is my sub nav graph:
<navigation
android:id="#+id/sub_graph_id"
app:startDestination="#id/fragment3">
<fragment
android:id="#+id/fragment3"
android:name="fragment3"
android:label="fragment3">
<action
android:id="#+id/action_fragment3_to_fragment4"
app:destination="#id/fragment4" />
</fragment>
<fragment
android:id="#+id/fragment4"
android:name="fragment4"
android:label="fragment4"/>
</navigation>
What am I missing? How should I achieve this?

Related

How can I back from the second fragment to the first fragment using Navigation Component?

How can I back from the second fragment to the first fragment using Navigation Component?
navigation_main.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/main_navigation"
app:startDestination="#id/firstFragment">
<fragment
android:id="#+id/firstFragment"
android:name="com.test.ttt.FirstFragment"
tools:layout="#layout/fragment_first">
<action
android:id="#+id/action_firstFragment_to_secondFragment"
app:destination="#id/secondFragment"
app:popUpTo="#id/firstFragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/secondFragment"
android:name="com.test.ttt.SecondFragment"
tools:layout="#layout/fragment_second" />
</navigation>
FirstFragment.java
public class FirstFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Navigation.findNavController(container).navigate(FirstFragmentDirections.actionFirstFragmentToSecondFragment());
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
I want when I press the back button in the second fragment, It must back to the first fragment but currently, When I press the back button in the second fragment it is leaving the app.
How can I solve this problem?
The reason you are being exited from the app is because while navigating to the second fragment, you are removing the first fragment from your stack. The properties app:popUpTo and app:popUpToInclusive are typically used when you want to remove some fragments from your backstack while navigating. A simple use case for this would be when navigating from Login/SignUp Fragment to Home/Main Fragment. In this case you would not want the user to be able to press back and go back to login/signup screens. Here is where the two properties would help.
TL;DR - Remove the app:popUpTo and app:popUpToInclusive properties from your action
Change
<action
android:id="#+id/action_firstFragment_to_secondFragment"
app:destination="#id/secondFragment"
app:popUpTo="#id/firstFragment"
app:popUpToInclusive="true"/>
to
<action
android:id="#+id/action_firstFragment_to_secondFragment"
app:destination="#id/secondFragment"/>

Android navigation component exclude fragment from back stack

I need to exclude Fragment from back stack.
I know there are many questions here regarding this issue, but I cousin't find an answer to my issue.
Let's say I have Fragment A and Fragment B. Fragment A is move to Fragment B and Fragment B open another Activity. What I need is when I click back from that Activity go back to Fragment A.
Below is my XML of the graph:
<fragment
android:id="#+id/nav_liabilities_fragment"
android:name="liabilities.liabilities_list_fragment.view.LiabilitiesListFragment"
android:label="LiabilitiesListFragment"
tools:layout="#layout/fragment_liabilities_list">
<action
android:id="#+id/action_nav_liabilities_fragment_to_nav_missing_liability_details_fragment"
app:destination="#id/nav_missing_liability_details_fragment"
app:popUpTo="#+id/nav_liabilities_fragment"
app:popUpToInclusive="false"
/>
</fragment>
<fragment
android:id="#+id/nav_missing_liability_details_fragment"
android:name="ui.flow.lobby.liabilities.missing_liability_details.view.MissingDetailsLiabilityFragment"
android:label="MissingDetailsLiabilityFragment"
tools:layout="#layout/fragment_missing_details_liability">
<argument
android:name="extra_data"
app:argType="android.repository.network.model.response.liabilities.LiabilityModel" />
</fragment>
</navigation>

Navigation graph with viewpager2 android

My viewpager consists of 2 fragments which are displayed correctly and working fine.
From viewpager's fragment I want to move to another fragment via navigation graph
This is my graph
<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/offer_nav_graph"
app:startDestination="#id/offersFragment">
<fragment
android:id="#+id/offersFragment"
android:name="com.octave.offers.OffersFragment"
android:label="offers_fragment"
tools:layout="#layout/offers_fragment" />
<fragment
android:id="#+id/availableOfferDetailFragment"
android:name="com.octave.offers.available.AvailableOfferDetailFragment"
android:label="fragment_available_offer_detail"
tools:layout="#layout/fragment_available_offer_detail" />
<fragment
android:id="#+id/availableOffersFragment"
android:name="com.octave.offers.available.AvailableOffersFragment"
android:label="fragment_available_offers"
tools:layout="#layout/fragment_available_offers" >
<action
android:id="#+id/action_availableOffersFragment_to_availableOfferDetailFragment"
app:destination="#id/availableOfferDetailFragment" >
<argument
android:name="offerId"
app:argType="integer"
android:defaultValue="-1" />
</action>
</fragment>
</navigation>
Offers fragment - has view pager
Available offer fragment - one of the fragment on view pager
Available offer detail fragment - i want to navigate
On button click I am calling this
AvailableOffersFragmentDirections.actionAvailableOffersFragmentToAvailableOfferDetailFragment(offerId)
The exception
Navigation action/destination com.octave.staging:id/action_availableOffersFragment_to_availableOfferDetailFragment cannot be found from the current destination Destination(com.octave.staging:id/homeFragment) label=HomeFragment class=com.octave.home.HomeFragment
What is wrong over here?
button exists on availableOffersFragment. I want to navigate from
availableOffersFragment to availableOfferDetailFragment.
offersFragment has the viewpager with 2 tabs having their own fragment
availableOffersFragment and secondFragemnt
So, now you need to navigate from availableOffersFragment which is a tab (page fragment) in the ViewPager; but this is not possible because those tabs don't affect the back stack. You can check out the questions discussed in here and also this one.
But what you can do instead is to add an action from offersFragment (which holds the ViewPager) to availableOfferDetailFragment as following:
Remove the tab fragments from the navGraph (availableOffersFragment and secondFragemnt).
Create an action in the navGraph from offersFragment to availableOfferDetailFragment
<fragment
android:id="#+id/offersFragment"
android:name="com.octave.offers.OffersFragment"
android:label="offers_fragment"
tools:layout="#layout/offers_fragment">
<action
android:id="#+id/action_offersFragment_to_availableOfferDetailFragment"
app:destination="#id/availableOfferDetailFragment" >
<argument
android:name="offerId"
app:argType="integer"
android:defaultValue="-1" />
</action>
</fragment>
When the button is clicked use parentFragment to access the offersFragment from the availableOffersFragment tab when the button is clicked. For instance:
Create a method in offersFragment:
goToDetailsFragment(offerId: Int) {
// perfrom the navaigation
OffersFragmentDirections.actionOffersFragmentToAvailableOfferDetailFragment(offerId)
}
And in availableOffersFragment
btn.setOnClickListener {
(parentFragment as offersFragment).goToDetailsFragment(offerId)
}
Check using:
btn.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.availableOfferDetailFragment)
}

Navigation Components conditional popUpTo?

Newbie on Navigation Component. I'm trying to achieve this but I don't know how:
I have 3 fragments:
FragmentA → FragmentList → FragmentAdd
If I try to go from FragmentMain to FragmentList but list is empty it should go directly to FragmentAdd (its not really directly since I'm checking the list on FragmentList but for the user it should look like it). If I'm on FragmentAdd and I go back (by either pressing back button or back on the toolbar) it should go back to FragmentMain (since FragmentList is still empty) but if I add something it should go back to FragmentList.
I've tried with
<fragment
android:id="#+id/fragmentMain" >
<action android:id="#+id/action_fragmentMain_to_fragmentList
app:destination="#id/fragmentList"
app:popUpTo="#id/fragmentMain"
app:popUpToInclusive="true"/>
</fragment>
The thing is that if I press back on FragmentAdd it will go to FragmentList, check that the list is still empty and go back to FragmentAdd. And if I pop FragmentList and then add something It will go to FragmentMain and not the list.
The difference with Conditional back navigation with Android Navigation Component is that I can add stuff to FragmentList from FragmentAdd
Any suggestion please?
Use app:popUpTo="#id/FragmentList" and app:popUpToInclusive="true" in action action_fragmentList_to_fragmentAdd
<fragment
android:id="#+id/fragmentMain" >
<action android:id="#+id/action_fragmentMain_to_fragmentList
app:destination="#id/fragmentList"/>
</fragment>
<fragment
android:id="#+id/fragmentList" >
<action android:id="#+id/action_fragmentList_to_fragmentAdd
app:destination="#id/fragmentAdd"
app:popUpTo="#id/fragmentList"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/fragmentAdd" >
</fragment>

How can I go back directly to Fragment A since Fragment D without going back to Fragment C?

I use Android Navigation Architecture Component.
I have three Fragment A, B and C
Fragment A -> Fragment B -> Fragment D
Fragment A -> Fragment C -> Fragment D
On fragment D I have a button used to validate modifications and finish.
From this Frgament D I would like to:
return to Fragment B when I come from Fragment B (I use findNavController().navigateUp())
come back to Fragment A when I come from Fragment C (I don't know how to do it)
How can I go back directly to Fragment A when I come from Fragment D without going back to Fragment C?
Should I wait for the return on Fragment C and reprocess for the execution of findNavController().NavigateUp().
I use setPopUpTo on NavOptions, or you can use it inside the xml as well
documentation => https://developer.android.com/reference/androidx/navigation/NavOptions.Builder#setPopUpTo(int,%20boolean)
You can achieve both of these action with findNavController().NavigateUp()
Given the following graph for example:
<?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/test_nav_graph"
app:startDestination="#id/a">
<fragment
android:id="#+id/a"
android:name="fragment.A"
tools:layout="#layout/a_fragment"
android:label="A" >
<action
android:id="#+id/action_a_to_b"
app:destination="#id/b" />
<action
android:id="#+id/action_a_to_c"
app:destination="#id/c" />
</fragment>
<fragment
android:id="#+id/b"
android:name="fragment.B"
tools:layout="#layout/b_fragment"
android:label="B" >
<action
android:id="#+id/action_b_to_d"
app:destination="#id/d" />
</fragment>
<fragment
android:id="#+id/c"
tools:layout="#layout/c_fragment"
android:name="fragment.C"
android:label="C" >
<action
android:id="#+id/action_c_to_d"
app:destination="#id/d"
app:popUpTo="#id/a"/>
</fragment>
<fragment
android:id="#+id/d"
tools:layout="#layout/d_fragment"
android:name="fragment.D"
android:label="D" />
</navigation>
When you take the path: A->B->D your back stack is A,B,D and when you call NavigateUp() you go back to B.
Now the path A->C->D has a minor addition in the action tag as you can see
<action
android:id="#+id/action_c_to_d"
app:destination="#id/d"
app:popUpTo="#id/a"/>
it has popUpTo, so when you navigate from C to D app:popUpTo tells the Navigation library to pop some destinations off of the back stack as part of the call to navigate(), so after navigating to D your back stack is A,D and NavigateUp() takes you back to A
So when you are in Fragment D and pressing back button . You can check the fragment stack and check for example
onBackPress(){
childFragmentManager.popbackstack()
val currentFragment = findFragmentByTag("FRAGMENT_B")
if(currentFragment == childFragmentManager.primaryNavigation()){
childFragmentManager.popbackstack()
}
NOTE
Above snippet is written without editor. You can use this logic.

Categories

Resources