Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skip some fragments onBackPressed

I am fairly new with android fragments so please bear with me.

I have a bunch of fragments using a single activity as host.

In my mind, my fragments are grouped by sections although they are still modular/reusable by code. Consider this desired scenario:

Frag1 -> (Press Next) -> Frag2 -> (Press Next) -> Frag3 -> (Press Back) -> Frag1

After going through a series of fragments, I would like to skip some previous fragments (in this scenario, skip Frag 2) on pressing the back button.

However, in my current code, my problem is that even though it goes back to Frag1, Frag3 does not disappear from the screen. What happens is that both Frag1 and Frag3 becomes visible on top of each other.

Here are my relevant code snippets:

Code snippet for creating Frag1

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    // init the fragment (with a default fragment, not null)
    Fragment fragment = PlaceholderFragment.newInstance(position + 1);
    // Position number from navigation sidebar starts from 0.
    // Since position starts from 0, add 1 to match section number
    // as implemented in {@link #onSectionAttached()}
    switch(position) {
        case 0:
            fragment = PlaceholderFragment.newInstance(position + 1);
            break;
        case 1: // Frag1 case
            fragment = new AddPointsFragment().newInstance(position + 1, "");
            break;
        default:
            break;
    }
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();
    // clear all fragments from previous section from the back stack
    fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    // replace all currently added fragments in container and replace with the new fragment
    fragmentManager.beginTransaction()
            .replace(R.id.container, fragment)
            .commit();
}

Code snippet for creating Frag2

public void onEnterButtonFragmentInteraction(int sectionNumber, String cardNo) {
    // TODO: Add point for given card number
    int points = 5; //sample points
    AddPointsSuccessFragment addPointsSuccessFragment =
            new AddPointsSuccessFragment().newInstance(sectionNumber, cardNo, points);
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.container, addPointsSuccessFragment)
            .addToBackStack(null)
            .commit();
}

Code snippet for creating Frag3

public void onOkButtonFragmentInteraction(int sectionNumber, String cardNo, int points) {
    RedeemRewardFragment redeemRewardFragment =
                new RedeemRewardFragment().newInstance(sectionNumber, cardNo, points);
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container, redeemRewardFragment);
        fragmentTransaction.commit();
}

My current workaround for this is by adding .addToBackStack(null) in creating Frag3 and running this code

public void onBackButtonFragmentInteraction() {
    this.onBackPressed(); // simulate pressing of activity back button
    FragmentManager fragmentmanager = getFragmentManager();
    fragmentmanager.popBackStack(); // pop Frag2 from back stack
}

right after calling the onBackPressed() method. Unfortunately, this workaround is ugly because because there is a split-second appearance of Frag2 before going to Frag1.

like image 297
Nico Dumdum Avatar asked Sep 16 '14 18:09

Nico Dumdum


2 Answers

So the key to your solution here is this guy:

.addToBackStack(null)

Instead of null, you can pass in a String identifier for that particular transaction -- for instance, the class name of the Fragment is what we use (although that doesn't work if you have multiple instances of the same fragment on the backstack):

.addToBackStack(Fragment1.class.getName())

Then, if you wanted to get back to Fragment1 from Fragment3, just pop using the identifier of the next fragment, and pass the INCLUSIVE flag (which means it will also pop that next fragment that you specified):

getFragmentManager().popBackStack(
        Fragment2.class.getName(), 
        FragmentManager.POP_BACK_STACK_INCLUSIVE);

Which will play your animations as expected, but as if the fragments in between were never there. The reason I suggest to use the next fragment is because you probably don't want your first fragment transaction on the back stack.

like image 113
Kevin Coppock Avatar answered Oct 07 '22 08:10

Kevin Coppock


You could try this, it should work and doesnt give a split-second delay. Its not beautiful code though, and if somebody has a better way, please post.

1.Give a tag to your fragments.

transaction.add(R.id.main_activity_container, FirstFragment, "FirstFragment");
transaction.replace(R.id.main_activity_container, Second, "SECOND");
transaction.replace(R.id.main_activity_container, Third, "THIRD");

2.Modify your onBackPressed() in your frameActivity (activity) that "houses" your fragments.

@Override
public void onBackPressed() {
    // TODO Auto-generated method stub

    int lastStack = getSupportFragmentManager().getBackStackEntryCount();
    try {
        //If the last fragment was named/tagged "three"
        if (getSupportFragmentManager().getFragments().get(lastStack).getTag().equalsIgnoreCase("THIRD")){

            getSupportFragmentManager().popBackStackImmediate();
            getSupportFragmentManager().popBackStackImmediate();

            //Get your first fragment that you loaded in the beginning. 
            Fragment first = getSupportFragmentManager().findFragmentByTag("FirstFragment");
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.main_activity_container, first);
            transaction.commit();
            return;
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    super.onBackPressed();
}
like image 41
user3711421 Avatar answered Oct 07 '22 09:10

user3711421