On Navigation Drawer back button is not working correctly?

3.4k Views Asked by At

Fragment Overlap

I have 5 fragments.On pressing back button I want to move to home fragment no matter how many fragments are opened.

If I move from

[1] --> [2] and Press back [1] shown home fragment

[1] --> [3] and Press back [1] shown home fragment

[1] --> [4] and Press back [1] shown home fragment

[1] --> [5] and Press back [1] shown home fragment

As I want No Problem.

But Problem is

[1] --> [2] --> [3] and Press back home fragment overlap on [3]

[1] --> [2] --> [4] and Press back home fragment overlap on [4]

[1] --> [2] --> [5] and Press back home fragment overlap on [5]

I have added only home fragment to backStack and used replace fragment method.

Why this is happening???

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.all_activity_layout);
    setToolbar();
    addFragment(AttractionsFragment.newInstance());
    setNavigationDrawer();
}

 @SuppressWarnings("StatementWithEmptyBody")
 @Override
 public boolean onNavigationItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.nav_attractions:
            if (mCurrentNavigationDrawerItem != 0) {
                mCurrentNavigationDrawerItem = 0;
                replaceFragment(AttractionsFragment.newInstance());
            }
            break;
        case R.id.nav_packages:
            if (mCurrentNavigationDrawerItem != 1) {
                mCurrentNavigationDrawerItem = 1;
                replaceFragment(PackagesFragment.newInstance());
            }
            break;
        case R.id.nav_passes:
            if (mCurrentNavigationDrawerItem != 2) {
                mCurrentNavigationDrawerItem = 2;
                replaceFragment(PassesFragment.newInstance());

            }
            break;
        case R.id.nav_coupons:
            if (mCurrentNavigationDrawerItem != 3) {
                mCurrentNavigationDrawerItem = 3;
                replaceFragment(CouponsFragment.newInstance());

            }
            break;
        case R.id.nav_more:
            if (mCurrentNavigationDrawerItem != 4) {
                mCurrentNavigationDrawerItem = 4;
                replaceFragment(MoreFragment.newInstance());
            }
            break;
    }

    mNavigationView.getMenu().getItem(mCurrentNavigationDrawerItem).setChecked(true);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

public void replaceFragment(Fragment fragment) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    // Get Current Visible fragment
    Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    // Add to back stack only if it is AttractionsFragment
    if (f instanceof AttractionsFragment) {
        transaction.addToBackStack(fragment.getClass().getName());
    }

    transaction.replace(R.id.fragment_container, fragment);
    transaction.commit();

    Log.d("Navigation", "BackStack Count:" + getSupportFragmentManager().getBackStackEntryCount());


}

public void addFragment(Fragment fragment) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.add(R.id.fragment_container, fragment, "AttractionsFragment");
    transaction.commit();
}

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

There are 6 best solutions below

4
On

Remove the transaction.addToBackStack(fragment.getClass().getName()); line it will work fine. Please check the code below

public void replaceFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Get Current Visible fragment
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
// Add to back stack only if it is AttractionsFragment

transaction.replace(R.id.fragment_container, fragment);
transaction.commit();

Log.d("Navigation", "BackStack Count:" + getSupportFragmentManager().getBackStackEntryCount());


 }
1
On

Replace your container view with first fragment:

@Override
public void onBackPressed() {

FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(R.id.fragment_container, new **your_first_fragment**()).commit();

DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
    drawer.closeDrawer(GravityCompat.START);
} else {
    super.onBackPressed();
}
}
5
On

If you are adding/launching all three fragments in the same activity, instead of the add() method of FragmentTransaction for showing Fragment3, use the replace() method of FragmentTransaction (replace Fragment2 with Fragment3). The replace method removes the current fragment from backstack before adding the new fragment. If you are launching Fragment3 from a different activity, and thus you can't/don't want to use replace(), remove Fragment2 from backstack before starting the new activity (which adds fragment3):

// in Fragment2, before adding Fragment3:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
               .remove(this) // "this" refers to current instance of Fragment2
               .commit();
fragmentManager.popBackStack();
// now go ahead and launch (add) fragment3
// if fragment3 is launched from a different activity, 
// start that activity instead
fragmentManager.beginTransaction()
               .add(R.id.a_container_view_in_activity, new Fragment3(),
                    Fargment3.FRAGMENT3_ID)
               .commit();

This will solve your problem. Try this..

1
On

You need to pop the 2nd fragment before navigating to 3rd fragment.

  Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    // Add to back stack only if it is AttractionsFragment
    if (f instanceof AttractionsFragment) {
        transaction.addToBackStack(fragment.getClass().getName());
    } else {
        activity.getSupportFragmentManager().popBackStackImmediate();
    }

    transaction.replace(R.id.fragment_container, fragment);
    transaction.commit();
6
On

try this:

in your onBackPressed:

    @Override
public void onBackPressed(){
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}

also in your replace fragment- to solve overlapping issue try

transaction.replace(((ViewGroup)(getView().getParent())).getId(), fragment);

or

getSupportFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit(); 

Try changing your code in replace fragment:

public void replaceFragment(Fragment fragment) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    // Get Current Visible fragment
    //Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    AttractionsFragment myFragment = (AttractionsFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
    if (myFragment != null && myFragment.isVisible()) {
        // Add to back stack only if it is AttractionsFragment
        transaction.addToBackStack(null);
    }
    transaction.replace(R.id.fragment_container, fragment, "MY_FRAGMENT");
    transaction.commit();

    Log.d("Navigation", "BackStack Count:" + getSupportFragmentManager().getBackStackEntryCount());

}
0
On

In OnBackpress add this code:

 @Override
        public void onBackPressed() {
            drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            if (drawer.isDrawerOpen(GravityCompat.START)) {
                drawer.closeDrawer(GravityCompat.START);
            } else {
                if (getFragmentManager().findFragmentById(R.id.activity_container) instanceof HomeFragment) {
                    super.onBackPressed();
                } else {
                        replaceFragment(this, new HomeFragment());
                    }
                }

And change your replaceFragment and AddFragment methods in all cases with the code given below:

 public void addFragment(final Activity mActivity, final Fragment newFragment, final Fragment hideFragment) {
            final FragmentManager fragmentManager = mActivity.getFragmentManager();
            final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.hide(hideFragment);
            fragmentTransaction.add(R.id.activity_container, newFragment, newFragment.getClass().getSimpleName());
            fragmentTransaction.addToBackStack(hideFragment.getClass().getSimpleName());
            fragmentTransaction.commitAllowingStateLoss();
        }
public void replaceFragment(final Activity mActivity, final Fragment newFragment) {
        final FragmentManager fragmentManager = mActivity.getFragmentManager();
        final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.activity_container, newFragment, newFragment.getClass().getSimpleName());
        fragmentTransaction.commit();
    }

Where activity_container is the FrameLayout Id in xml file of the activity.

In onCreate of your activity call replaceFragment method instead of addFragment. And in all navigation item click event, call replaceFragment method.