Search code examples
androidfragmentfragmentmanager

Fragment not being deleted after calling .remove(fragment)


I am overriding the onBackPressed function to change the behavior of the back key for an app I am working on.

If a the FragmentTransaction contains a fragment with a certain tag qFrag then I want it to animate the fragment from the view.

However after I remove the fragment, it still appears to be there. Because of this it never reaches the else condition of my if statement.

 @Override
public void onBackPressed() {
    // After pressing the back key a second time, questionFrag still has a value.
    Fragment questionFrag = getSupportFragmentManager().findFragmentByTag("qFrag");

    // If question fragment in the fragment manager
    if (questionFrag != null) {
        getSupportFragmentManager()
                .beginTransaction()
                .setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
                .replace(R.id.main_menu_content_frame_layout, new Fragment(), "temp")
                .remove(questionFrag)
                .commit();

    } else {
        finish();
    }

}

Can someone advise me on how to appropriately remove fragments from the transaction manager?


Solution

  • There are two things you need to know about fragments in this subject:

    1 - When you give a tag to a fragment and add it to back stack which you most certainly are, this:

    Fragment questionFrag = getSupportFragmentManager().findFragmentByTag("qFrag");
    

    only returns null if you call popBackStack(). Since you are not calling it the fragment is still stored in the backstack even if you call remove on it.

    2- This bit of code

    .replace(R.id.main_menu_content_frame_layout, new Fragment(), "temp")
    .remove(questionFrag)
    

    is redundat since when you call replace you are calling remove on every fragment that is in the given container, and then add the new one so this

    .replace(R.id.main_menu_content_frame_layout, new Fragment(), "temp")
    

    is enough.

    Now, there are two ways too solve your problem which are:

    poping the back stack after replace:

    if (questionFrag != null) {
        getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.main_menu_content_frame_layout, new Fragment(), "temp")
            .setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
            .commit();
    
         getSupportFragmentManager().popBackStack();    
    
         System.out.println("questionFrag removed successfully");
    
        finish()
    } else {
        finish();
    }
    

    Or, instead of poping the backstack, verify if the fragment is in the container

    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_menu_content_frame_layout);
    
    if(fragment instanceOf QuestionFragment){
         getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.main_menu_content_frame_layout, new Fragment(), "temp")
            .setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
            .commit();
    
         getSupportFragmentManager().popBackStack();    
    
         System.out.println("questionFrag removed successfully");
    
        finish()
    
    } else {
        finish();
    }