In my app (minSdkVersion
15) I have a Toolbar
instead of ActionBar
and NavigationDrawer
switching between fragments. Some fragments have TabBar
with child fragments inside. These child fragments are ListView
s, and their onItemClickListener
triggers DetailFragment
. I call setDisplayHomeAsUpEnabled()
and an up arrow appears for DetailFragment
but I can't treat it to perform any action, or even show a toast. I've tried this and handling switch (item.getItemId())
in onOptionsItemSelected()
but neither solution works for me. I'm missing something but can't recognize what.
Here's my code:
public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener {
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Listen for changes in the back stack
getSupportFragmentManager().addOnBackStackChangedListener(this);
//Handle when activity is recreated like on orientation Change
shouldDisplayHomeUp();
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
final ActionBar actionBar = getSupportActionBar(); //...
...
public void shouldDisplayHomeUp(){
//Enable Up button only if there are entries in the back stack
boolean canback = getSupportFragmentManager().getBackStackEntryCount()>0;
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(canback);
actionBarDrawerToggle.setDrawerIndicatorEnabled(!canback);
}
}
@Override
public boolean onNavigateUp() {
//This method is called when the up button is pressed. Just the pop back stack.
getSupportFragmentManager().popBackStack();
return true;
}
@Override
public void onBackStackChanged() {
shouldDisplayHomeUp();
}
My entire onOptionsItemSelected
:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case android.R.id.home:
Toast.makeText(this, "Up button!", Toast.LENGTH_SHORT).show();
//called when the up affordance/carat in actionbar is pressed
onBackPressed();
break;
case R.id.action_search:
Toast.makeText(this, "Search", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
I don't know if this other code matters:
// Initializing Drawer Layout and ActionBarToggle
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar,R.string.openDrawer, R.string.closeDrawer){//...
//Setting the actionbarToggle to drawer layout
mDrawerLayout.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessay or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
In my manifest I have no parent activity.
I found this and it seems to be the right answer but I don't understand how to implement it and have no reputation to ask author.
What can I try to get the up button working?
Two new questions: when I set
public void shouldDisplayHomeUp(){
//Enable Up button only if there are entries in the back stack
if (getSupportActionBar() != null) {
if (getSupportFragmentManager().getBackStackEntryCount()>0) {
actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
}
...and from the child fragment I press the hardware "back" button I return to the previous fragment and the hamburger icon appears. But the up button still doesn't response from the child fragment. I believe it's because ActionBarDrawerToggle
doesn't manage its behavior anymore. But who manages it instead? If I set this method like this:
public void shouldDisplayHomeUp(){
//Enable Up button only if there are entries in the back stack
if (getSupportActionBar() != null) {
if (getSupportFragmentManager().getBackStackEntryCount()>0) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}
}
}
...then ActionBarDrawerToggle
handles the click on the up button and opens the drawer like the hamburger icon does. But when I press the hardware back button, the up button (arrow) disappears and the hamburger icon doesn't appear.
So now I see two ways to resolve this problem. First, I could figure out who manages the up button when
actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
and
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
or otherwise, how can I override the ActionBarDrawerToggle
behavior to perform another action when the up button arrow is available instead of the hamburger icon? And how to cause the hamburger icon to appear when I press the hardware back button?
Answer is simple as I expected but I spend more than a day to get this clear. I implemented drawer step by step discovering documentation for every method. Ran app to notice any changes. I figured out that when setDisplayHomeAsUpEnabled(true) it's only changes drawer hamburger icon on back arrow icon but when you click the back arrow it performs same action (show-hide the drawer).
When you want to implement another behavior for back arrow you should setDrawerIndicatorEnabled(false) too then setToolbarNavigationClickListener(). So
public void shouldDisplayHomeUp(){
//Enable Up button only if there are entries in the back stack
if (getSupportActionBar() != null) {
if (getSupportFragmentManager().getBackStackEntryCount()>0) {
actionBarDrawerToggle.setDrawerIndicatorEnabled(false); // order matters
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
and
actionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "ToolbarNavigationClickListener", Toast.LENGTH_SHORT).show();
}
});
work together fine to implement custom UpButton behavior. Hope it'll help somebody.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With