Android ViewPageAdapter with a separate foot for each tab

I have an android application with one action. This activity contains a SlidingTabLayout with a ViewPageAdapter, as in this example. Each tab contains a corresponding root fragment, which is then replaced with other fragments when the user uses this screen. A visual representation is shown below:

enter image description here

In my current implementation, I do the following: go to tab1, ProductListFragment will load immediately, replacing ProductRootFragment with ProductListFragment. I click on a product and replace ProductListFragment with ProductDetailFragment. Now I switch to tab2 and Tab2ListFragment loads immediately, replacing Tab2RootFragment. I click on an element, and Tab2DetailFragment replaces Tab2ListFragment. Now I'm returning to Tab1 and, as I suppose, ProductDetailFragment is still displayed. However, if I click the back button now, it will not return me to ProductListFragment, as I expect. Instead, it pops a Tab2DetailFragment from the backstack.

I want to implement a separate freeze frame for each fragment of the "tab". There are several reports about this, but they all seem to be outdated, and some offer very complex solutions. (Here here , here and here ...)

It seems that in recent versions of the SDK, the Android can automatically process this backstack hierarchy without having to manually implement some kind of backstack using getChildFragmentManager, rather than getSupportFragmentManager in my transactions, where I replace fragments. However, I could not get this to work. (I intuitively feel that the right solution is to let Android handle this, as it feels that it manually overrides the back button, and implementing its own stack is a difficult hack.)

Can someone explain how to correctly implement the expected behavior when a separate stack is supported for each tab? Or perhaps a link to a simple, well-designed and modern example of how to achieve the desired behavior?

Additional information about my code: In my MainActivity.java, I create a ViewPagerAdapter using getSupportFragmentManager ().

ViewPagerAdapter.java

@Override public Fragment getItem(int position) { switch(position){ case 0: return new ProductRootFragment(); ... } ... } 

ProductRootFragment.java

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.product_root_fragment, container, false); FragmentTransaction transaction = getFragmentManager() .beginTransaction(); transaction.replace(R.id.product_root_container, new ProductListFragment()); transaction.commit(); return view; } 

ProductListFragment.java

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.product_list_fragment, container, false); view = (ProductListView) layout; return view; } ... @Override public void onListItemClick(ListView l, View v, int position, long id) { ... ProductDetailFragment newFragment = new ProductDetailFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.product_root_container, newFragment); transaction.addToBackStack(null); transaction.commit(); } 

ProductDetailFragment.java

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = (ProductDetailView) inflater.inflate(R.layout.product_detail_fragment, container, false); return view; } 
+5
source share
2 answers

I know that it’s too late to answer this question, but maybe someone else needs it. To do this, you should use getChildFragmentManager() instead of getFragmentManager() in your root fragments

For example, I have activity with ViewPager and TabLayout, and I add RootFragment1 and RootFragment2 to ViewPager and configure TabLayout using ViewPager. Now in my RootFragment1 to replace my Tab1Fragment1 I use this code:

 final FragmentTransaction ft = getChildFragmentManager().beginTransaction(); ft.replace(R.id.RootFrame1, Tab1Fragment1.newInstance(), "MyTag"); ft.commit(); 

And I need a method for the pop-up fragment from backstack like this:

 public boolean popBackStack() { if(getChildFragmentManager().getBackStackEntryCount() > 0) { getChildFragmentManager().popBackStackImmediate(); return true; } else return false; } 

And for example, I have a button in Tab1Fragment1 that replaces the Tab1Fragment2 fragment Tab1Fragment2 the current one. The onClickListener button should look like this:

 button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.RootFrame1, Tab1Fragment2.newInstance(), "MyTag"); ft.addToBackStack(null); ft.commit(); } }); 

I do the same with the second fragment ( RootFragment2 ).

After that, now I only need to override the onBackPressed() my MainActivity below:

 @Override public void onBackPressed() { if (viewPager.getCurrentItem() == 0) { RootFragment1 fragment = ((RootFragment1) sectionsPagerAdapter.getItem(0)); if (!fragment.popBackStack()) super.onBackPressed(); } else if (viewPager.getCurrentItem() == 1) { RootFragment2 fragment = ((RootFragment2) sectionsPagerAdapter.getItem(1)); if (!fragment.popBackStack()) super.onBackPressed(); } else super.onBackPressed(); } 

What I check is, if each tab contains a fragment, then I get the back.stack else call super.onBackPressed() to perform the default action.

+2
source

you get this problem because every time you replace a fragment, you add that fragment to the back stack. Backstack is supported for the fragment, depending on the activity in which the fragment is added. so every time you do addToBackStack() , it maintains in the same activity. and when you try to use your script, the last piece added, which is at the top of the backstack, is Tab2DetailFragment. To solve this problem, you need to clear the stack each time you switch to another tab. remember that you need to clear the entire fragment from the backstack, not the activity.

0
source