I\'m using the built-in navigation drawer to run my app. I can\'t quite figure out how to handle the back button. When it\'s pressed I want it to load the very first fragmen
I would suggest avoiding an override of onBackPressed()
altogether by managing your transactions properly in the first place. This will help to avoid having to implement crazy logic down the road.
To do this first we need to set a private class variable in that will enable initialization:
private boolean popNext = false;
The following code allows us to setup the initial back function by placing it on the stack. Every time thereafter, when popNext
is set to true, we pop the initial transaction and push the new one. So we are replacing the 1>X transaction with the 1>Y transaction.
The extra embedded if
statements deal with selecting the initial item, since we don't want to go from 1>1. If it's our initial case we just close the drawer. The other case needs to act like the back button, but we need to remember to set it as if it is returning to the initial state!
if(popNext){
if(i == INITIAL_POSITION){
onBackPressed();
mDrawerLayout.closeDrawer(mDrawerList);
popNext = false;
return;
}
getFragmentManager().popBackStackImmediate();
}
else{
if(i == INITIAL_POSITION){
mDrawerLayout.closeDrawer(mDrawerList);
return;
}
popNext=true;
}
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
Note: My code uses getFragmentManager()
instead of getSupportFragmentManager()
which is a native function, I believe as of Honeycomb.
Just wanted to report my findings even though this question is a little old for anyone else who may have had the same problem with the accepted answer. For me, doing the method suggested in the accepted answer, made the layers overlap, quickly making them unreadable. The code below (adapted from the accepted answer) avoids the overlaying but still adds the screen to the back stack.
fragmentManager.beginTransaction().replace(R.id.container, fragment).addToBackStack("fragBack").commit();
I have 4 fragment attached to bottomnavigation activity and i recently got into this problem and successfulyy solved as follows my activity code
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;
import android.os.Bundle;
import android.view.MenuItem;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class BottomNavigationActivity extends AppCompatActivity
{
NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_navigation);
BottomNavigationView bottomNavigationView=findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new FragmentHome()).commit();
}
public boolean onSupportNavigateUp() {
return navController.navigateUp();
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener= new
BottomNavigationView.OnNavigationItemSelectedListener()
{
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item)
{
Fragment selectedFragment = null ;
switch (item.getItemId())
{
case R.id.nav_home:
selectedFragment = new FragmentHome();
break;
case R.id.nav_search:
BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.commit();
selectedFragment=new FragmentSearch();
break;
case R.id.nav_cart:
BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.commit();
selectedFragment=new FragmentCart();
break;
case R.id.nav_user:
BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.commit();
selectedFragment= new FragmentAccount();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selectedFragment).commit();
return true;
}
};
@Override
public void onBackPressed()
{
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount == 0) {
super.onBackPressed();
} else
{
goHome();
}
}
public void goHome()
{
//Following code will set the icon of the bottom navigation to active
final BottomNavigationView mBottomNav = findViewById(R.id.bottom_navigation);
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
mBottomNav.setSelectedItemId(homeItem.getItemId());
getSupportFragmentManager().popBackStackImmediate();
//To delete all entries from back stack immediately one by one.
int backStackEntry = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackEntry; i++) {
getSupportFragmentManager().popBackStackImmediate();
}
//To navigate to the Home Fragment
final FragmentHome homeFragment = new FragmentHome();
FragmentTransaction myFragmentTransaction = getSupportFragmentManager().beginTransaction();
myFragmentTransaction.replace(R.id.fragment_container, homeFragment, "HomeFrag Tag");
myFragmentTransaction.commit();
}
}
Instead of:
fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();
Call:
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();
addToBackStack works with add
.
replace
function removes previous fragment and places new fragment so on your back-stack there is only one fragment all the time. So use add function to keep previous fragments on stack.
To always goto fragemnt1 from any fragment onBackPress try to do following:
getFragmentManager().popBackStack();
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();
this will remove last transaction from backstack and add new one. Try this.
In some cases you have to use replace then you cant work with addtobackstack() so you can use this code in MainActivity. In this code when you press back key you always go to first fragment (i call it HomeFragment) and when you are in HomeFragment it ask twice time to go out from application.
private Boolean exit = false;
@Override
public void onBackPressed() {
if (exit) {
super.onBackPressed();
return;
}
try {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag("HOME");
if (fragment != null) {
if (fragment.isVisible()) {
this.exit = true;
Toast.makeText(this, "Press Back again to Exit", Toast.LENGTH_SHORT).show();
}
}
else {
fragment = HomeFragment.class.newInstance();
getFragmentManager().popBackStack();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, "HOME").commit();
}
} catch (Exception e) {
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 2000);
}
- @Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
int backstack = getSupportFragmentManager().getBackStackEntryCount();
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (backstack > 0) {
for (int i = 0; i < backstack; i++) {
getSupportFragmentManager().popBackStackImmediate();
}
} else {
this.finish();
}
}