Is there anyway to swap or reorder fragment BackStack entry?
Asked Answered
R

6

9

am creating multiple fragment app, which require easy changing of fragment tabs, whose BackStack entry must be kept. On user click fragment must be pop up immediate. I think reordering BackStack is the best option. Do anyone know how to reorder BackStack ?

I have 5 fragments A,B,C,D,E. if user open fragment like A ---> B ---> C ---> D ---> E . using default back stack,back key it works fine. But when user opens A ---> B ---> C ---> D ---> E ---> B. After this if user click back, default back stack will goes to A.

Roving answered 8/9, 2016 at 1:10 Comment(3)
how about use show/hide fragment instead of push them to back stack ?Weissmann
show and hide not working, thats why i thought about thisRoving
How's your code so far?Keratitis
M
0

use non-swipable viewpager and on addOnPageChangeListener create arraylist and save all pages that opened. onBackPressed will compare arraylist and show pages.

Mavismavra answered 30/9, 2016 at 5:23 Comment(0)
B
1

There is no api for this usecase, but there are other means to do so:

Example

FragmentBackStackModifyActivity

Bencion answered 8/9, 2016 at 2:7 Comment(1)
but its for removing fragment from back stack not swaping or reordering, and id is based on index of addRoving
J
0

The user follows the path A ---> B ---> C ---> D ---> E then he wants to come to B. So what you should do is:

  • check if B is already in the back stack or not.
  • If it is there, then popBackStackImmediate to return to B
  • If it is not there, then add the fragment B normally.

So replace fragment should be something like this:

public void replaceFragment(Fragment fragment) {
    String fragmentTag =  fragment.getClass().getCanonicalName(); //unique name for the fragment, which will be used as tag.

    FragmentManager fragmentManager = getSupportFragmentManager();
    boolean isPopped = fragmentManager.popBackStackImmediate(fragmentTag, 0); // trying to return to the previous state of B if it exists.

    if (!isPopped && fragmentManager.findFragmentByTag(fragmentTag) == null){ // fragment is not in the backstack, so create it.
        FragmentTransaction ft = fragmentManager.beginTransaction();
        ft.replace(R.id.frame_layout, fragment, fragmentTag);
        ft.addToBackStack(fragmentTag);
        ft.commit();
    }
}

Remember, this will return to the previous state of B.

TIP: Since you don't want two instances of any fragment, So try to create a singleton instance of them. Because, if you are creating a new instance of the fragment and that fragment already exists in the back stack then the new instance will be ignored (because you are returning to the previous state).

Jandel answered 19/9, 2016 at 12:20 Comment(6)
my issue is that, when back to fragment B above fragment stack will lossesMavismavra
@BincyBaby Yes, if the stack is A ---> B ---> C ---> D ---> E and then you open B, the stack will change to A ---> B.Jandel
but i want to keep it in stack other c,d,e if tab changed.Mavismavra
You can't go to some middle node in a stack without popping all the top nodes. That violates stack property. If you are implementing tabs, then you should use ViewPager. :)Jandel
You can achieve that. Just link the ViewPager with tabs and disable the swipe gesture.Jandel
Let us continue this discussion in chat.Mavismavra
H
0

You Can Try this...

onBackpressed

 @Override
public void onBackPressed() {


  Fragment f = getSupportFragmentManager().findFragmentById(R.id.frame_container);
  if (f instanceof FragmentE)
{
     FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-1).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);


} else if (f instanceof FragmentD) {

 FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

}

else if (f instanceof FragmentC) {

 FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-3).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

}

else if (f instanceof FragmentB) {

 FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-4).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

}
   else
{
        super.onBackPressed();

 }
}

for back remove stack

 final android.app.FragmentManager fm = getFragmentManager();

    fm.addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {

            if (getSupportFragmentManager().getBackStackEntryCount() ==0) {
               // dLayout.closeDrawers();
                finish();
            }
            else
            {
               // dLayout.closeDrawers();

            }
        }
    });
Hally answered 21/9, 2016 at 5:31 Comment(0)
M
0

May be call addToBackstack() only when the fragment is not added before

Suppose as in your case when user is in Fragment E and when user calls Fragment B check if the Fragment B is already added in back stack

if yes, Then dont call addToBackstack for that FragmentTransaction.

else ,call addToBackstack()

check my sample code:

 private void addFragment (Fragment fragment){
        boolean isFragment=false;
        String backStateName = fragment.getClass().getName();
        FragmentManager fm = getFragmentManager();

        for(int entry = 0; entry < fm.getBackStackEntryCount(); entry++){
            Log.i(TAG, "Found fragment: " + fm.getBackStackEntryAt(entry).getId());
            if(fm.getBackStackEntryAt(entry).getId().equalsIgnoreCase(FragmentB))// check if fragment is in back stack
            {
                isFragment=true;
            }
        }

        if (!isFragment){ //fragment added to back stack, create it.
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragmentContainer, FragmentB).addToBackStack(FragmentB).commit();
        }else {//else dont call addToBackStack()
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragmentContainer, FragmentB).commit();
        }
    }
Motif answered 22/9, 2016 at 9:30 Comment(0)
D
0

Just place this code in your MainActivity

   @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            //super.onBackPressed();

            if (getFragmentManager().getBackStackEntryCount() == 1) {
                finish();
            }
            getFragmentManager().popBackStack();
        }
    }

Here getFragmentManager().getBackStackEntryCount() == 0 will checks that whether the stack entry is at 0 or not, if it's on 0 then the Activity will be finished.

In your case A --> B --> C --> D --> E --> B

A will be on 0,
B will be on 1,
C on 2,
D on 3,
E on 4,
B on 5

So when you click on back, the if condition will checks that the backstack count is on 0.

Dorena answered 23/9, 2016 at 9:50 Comment(0)
M
0

use non-swipable viewpager and on addOnPageChangeListener create arraylist and save all pages that opened. onBackPressed will compare arraylist and show pages.

Mavismavra answered 30/9, 2016 at 5:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.