سؤال

I have a sequence of event via which i have added three fragments to the backstack, one by one. Each of these fragments covers the full screen of the activity.

I have stored the is returned from the commit of Frag1.

Now in Frag3, based on a specific click, I want to go back to Frag1 directly and discard/pop all Fragments in between.

So, when this button is clicked i send a message to the activity which does the following:

getSupportFragmentManager().popBackStack(mFrag1Id, FragmentManager.POP_BACK_STACK_INCLUSIVE);

But i just got a blank screen, so i assume no fragment was loaded.

I even tried: In commit - fragmentTransaction.addToBackStack("Fragment1"); and then

getSupportFragmentManager().popBackStack("Fragment1", FragmentManager.POP_BACK_STACK_INCLUSIVE);

But it doesn't work. Could someone please help me with this?

Thanks.

هل كانت مفيدة؟

المحلول

OK so I found the issue.

FragmentManager.POP_BACK_STACK_INCLUSIVE pops all the fragments including the one whose id passed as argument.

SO for example:

getSupportFragmentManager().popBackStack(mFrag1Id, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Here it will pop everything on the stack including fragment whose id id mFrag1Id.

نصائح أخرى

When you opened Fragment A and you Navigated to Fragment B and then to Fragment C and then You want to close Fragment C and B and land on Fragment A

Now in some scenario, you want to close Fragment C and Fragment B and you want to land on Fragment A... then use this logic of FragmentManager to do such task.

  1. First get the number of fragment entries in back stack (When we are adding any fragment to addToBackStack("Frag1")) at that time fragment back stack entry will increase.

so get using this

FragmentManager fmManager = activity.getSupportFragmentManager();
Log.e("Total Back stack Entry: ", fmManager.getBackStackEntryCount() + "");

Now assume, you want to close current fragment (Fragment C) and your last fragment (Fragment B) so simple logic is getBackStackEntryCount -2 and at that time your back stack entry count will be 3 (Fragment A, Fragment B and Fragment C)

Here -2 is for because we want to go 2 fragment step back (Fragment C and Fragment B)

So simple two line of Code is:

if (fmManager.getBackStackEntryCount() > 0) {
fmManager.popBackStack(fmManager.getBackStackEntryAt(fmManager.getBackStackEntryCount()-2).getId(), FragmentMaanger.POP_BACK_STACK_INCLUSIVE);
}

You can also do it by adding two time "popBackStack()" and will also work, but it not idle way to do this

FragmentManager fmManager = activity.getSupportFragmentManager();
fmManager.popBackStack();
fmManager.popBackStack();

from third fragment you should call popBackStack(); twice (one to remove third fragment and the second to remove second fragment )

android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.remove(ThirdFragment.this);
transaction.commit();
fm.popBackStack();
fm.popBackStack();

If you want user to back at the beginning fragment, code snippet below will help you.

public static void popBackStackInclusive(AppCompatActivity activity) {

    FragmentManager fragmentManager = activity.getSupportFragmentManager();

    for (int i = 1; i < fragmentManager.getBackStackEntryCount(); i++){
        try {
            int fragmentId = fragmentManager.getBackStackEntryAt(i).getId();
            fragmentManager.popBackStack(fragmentId, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        } catch (Exception e) {
            Timber.d("Fragment Back Stack Error: %s", e.getLocalizedMessage());
        }
    }

}

Also if you want to prevent user to close app when no fragments at back stack, take a look at below.

@Override
public void onBackPressed() {
    FragmentManager fragmentManager = getSupportFragmentManager();

    if(fragmentManager.getBackStackEntryCount() > 1) {
        super.onBackPressed();
    } else {
        // TODO: Show dialog if user wants to exit app or;
        //finish();
    }
}

When user go [1] > [2] > [3]

Then onBackPress user will be [3] > [1].

Add in that fragment which you want to not show in backPress. No matter how many fragments you have. you can popUp any fragment between any two fragments

follow these 2 steps inside [2nd] fragment: that you want to popUp/close

Step1. Just add fragmentManager.popBackStack(); before fragmentTransaction mean calling [3] fragment. (after this line, It destroy/pop 2nd fragment and open 1st fragment again before open 3rd fragment. It mean when users press back button on 3rd fragment. then in recent fragment, there is 1st fragment not 2nd)
Step2. add .addToBackStack(null) also with fragmentTransaction

enter image description here

[2] Fragment : here on button click we will open 3rd fragment .

{ //.....
        //this code inside [2]nd fragment. onBackPress at [3] we want to close[2] between [3]>[1]

        //on button click listener
        view.findViewById(R.id.btnOpen3ndFrag).setOnClickListener(v -> {

            if (getActivity() != null) {
                FragmentManager fragmentManager = getActivity().getSupportFragmentManager();

                //this  .popBackStack will close this [2]nd fragment. before open 3rd fragment
                fragmentManager.popBackStack(); //<<<Step1: add this before fragmentTransaction

                //here we will open 3rd fragment
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, new ThirdFragment(), "FirstFragment")
                        .addToBackStack(null) //<<Step2: add this also.
                        .commit();
            } else {
                Toast.makeText(getActivity(), "Something went wrong", Toast.LENGTH_SHORT).show();
            }
        });

        //....
    }

(^_^) Happy Coding

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top