Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UpButton doesn't work whatever I try to do

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 ListViews, 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?

like image 463
AlexKost Avatar asked Oct 19 '22 09:10

AlexKost


1 Answers

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.

like image 196
AlexKost Avatar answered Oct 21 '22 23:10

AlexKost