How to get a Fragment to remove itself, i.e. its equivalent of finish()?

Android

Android Problem Overview


I'm converting an app to use fragments using the compatibility library. Now currently I have a number of activities (A B C D) which chain onto one another, D has a button 'OK' which when pressed calls finish which then bubbles up through onActivityResult() to additionally destroy C and B.

For my pre Honycomb fragment version each activity is effectively a wrapper on fragments Af Bf Cf Df. All activities are launched via startActivityForResult() and onActivityResult() within each of the fragments can happily call getActivity().finish()

The problem that I am having though is in my Honeycomb version I only have one activity, A, and fragments Bf, Cf, Df are loaded using the FragmentManager.

What I don't understand is what to do in Df when 'OK' is pressed in order to remove fragments Df, Cf, and Bf?

I tried having the fragment popping itself off the stack but this resulted in an exception. onActivityResult() is useless because I have not loaded up the fragment using startActivityForResult().

Am I thinking about this completely the wrong way? Should I be implementing some sort of listener that communicates with either the parent fragment or activity in order to do the pop using the transaction manager?

Android Solutions


Solution 1 - Android

While it might not be the best approach the closest equivalent I can think of that works is this with the support/compatibility library

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

or

getActivity().getFragmentManager().beginTransaction().remove(this).commit();

otherwise.

In addition you can use the backstack and pop it. However keep in mind that the fragment might not be on the backstack (depending on the fragmenttransaction that got it there..) or it might not be the last one that got onto the stack so popping the stack could remove the wrong one...

Solution 2 - Android

You can use the approach below, it works fine:

getActivity().getSupportFragmentManager().popBackStack();

Solution 3 - Android

> What I don't understand is what to do in Df when 'OK' is pressed in order to remove fragments Df, Cf, and Bf?

Step #1: Have Df tell D "yo! we got the OK click!" via calling a method, either on the activity itself, or on an interface instance supplied by the activity.

Step #2: Have D remove the fragments via FragmentManager.

The hosting activity (D) is the one that knows what other fragments are in the activity (vs. being in other activities). Hence, in-fragment events that might affect the fragment mix should be propagated to the activity, which will make the appropriate orchestration moves.

Solution 4 - Android

You should let the Activity deal with adding and removing Fragments, as CommonsWare says, use a listener. Here is an example:

public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {
    
    // onCreate etc

    @Override
    public void onFragmentSuicide(String tag) {
        // Check tag if you do this with more than one fragmen, then:
        getSupportFragmentManager().popBackStack();
    }
}

public interface SuicidalFragmentListener {
    void onFragmentSuicide(String tag);
}

public class MyFragment extends Fragment {
    
    // onCreateView etc

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
           suicideListener = (SuicidalFragmentListener) activity;
        } catch (ClassCastException e) {
           throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Attach the close listener to whatever action on the fragment you want
        addSuicideTouchListener();
    }

    private void addSuicideTouchListener() {
        getView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              suicideListener.onFragmentSuicide(getTag());
            }
        });
    }
}

Solution 5 - Android

In the Activity/AppCompatActivity:

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
        // if you want to handle DrawerLayout
        mDrawerLayout.closeDrawer(GravityCompat.START);
    } else {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }
}

and then call in the fragment:

getActivity().onBackPressed();

or like stated in other answers, call this in the fragment:

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

Solution 6 - Android

If you are using the new Navigation Component, is simple as

findNavController().popBackStack()

It will do all the FragmentTransaction in behind for you.

Solution 7 - Android

See if your needs are met by a DialogFragment. DialogFragment has a dismiss() method. Much cleaner in my opinion.

Solution 8 - Android

I create simple method for that

popBackStack(getSupportFragmentManager());

Than place it in my ActivityUtils class

public static void popBackStack(FragmentManager manager){
        FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
        manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

It's work great, have fun!

Solution 9 - Android

If you need to popback from the fourth fragment in the backstack history to the first, use tags!!!

When you add the first fragment you should use something like this:

getFragmentManager.beginTransaction.addToBackStack("A").add(R.id.container, FragmentA).commit() 

or

getFragmentManager.beginTransaction.addToBackStack("A").replace(R.id.container, FragmentA).commit()

And when you want to show Fragments B,C and D you use this:

getFragmentManager.beginTransaction.addToBackStack("B").replace(R.id.container, FragmentB, "B").commit()

and other letters....

To return to Fragment A, just call popBackStack(0, "A"), yes, use the flag that you specified when you add it, and note that it must be the same flag in the command addToBackStack(), not the one used in command replace or add.

You're welcome ;)

Solution 10 - Android

OnCreate:

//Add comment fragment
            container = FindViewById<FrameLayout>(Resource.Id.frmAttachPicture);
            mPictureFragment = new fmtAttachPicture();

            var trans = SupportFragmentManager.BeginTransaction();
            trans.Add(container.Id, mPictureFragment, "fmtPicture");
            trans.Show(mPictureFragment); trans.Commit();

This is how I hide the fragment in click event 1

//Close fragment
    var trans = SupportFragmentManager.BeginTransaction();
    trans.Hide(mPictureFragment);
    trans.AddToBackStack(null);
    trans.Commit();

Then Shows it back int event 2

var trans = SupportFragmentManager.BeginTransaction();
            trans.Show(mPictureFragment); trans.Commit();

Solution 11 - Android

To Close a fragment while inside the same fragment

getActivity().onBackPressed();

kotlin -

requireActivity().onBackPressed()

Solution 12 - Android

parentFragmentManager.apply {
    val f = this@MyFragment
    beginTransaction().hide(f).remove(f).commit()
}

Solution 13 - Android

Why not just:

getActivity().finish();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPJLView Question on Stackoverflow
Solution 1 - AndroidManfred MoserView Answer on Stackoverflow
Solution 2 - AndroidEric YuanView Answer on Stackoverflow
Solution 3 - AndroidCommonsWareView Answer on Stackoverflow
Solution 4 - AndroidBlundellView Answer on Stackoverflow
Solution 5 - AndroidCodeversedView Answer on Stackoverflow
Solution 6 - AndroidGastón SaillénView Answer on Stackoverflow
Solution 7 - AndroidVasudevView Answer on Stackoverflow
Solution 8 - AndroidEliasz KubalaView Answer on Stackoverflow
Solution 9 - AndroidDiego Ramírez VásquezView Answer on Stackoverflow
Solution 10 - AndroidCodeSiView Answer on Stackoverflow
Solution 11 - AndroidDino SunnyView Answer on Stackoverflow
Solution 12 - AndroidNicholas ChenView Answer on Stackoverflow
Solution 13 - AndroidWillView Answer on Stackoverflow