Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toolbar - Switching from drawer to back button with only one Activity

I've been searching for a while on how to change between the drawer open/close icon (going from a hamburger to the arrow) to a simple back arrow. My application at the moment only has one Activity which switches between several fragments. At one point, I want to transition between one of the main fragments (ie, one of the fragments in the drawer) to a fragment that hierarchically is under the previous fragment (ie, an "Add New " fragment). In this new fragment, I want to have the Toolbar to show the back button instead of the drawer button.

I've been looking around and trying different solutions for quite a while. Here are the most notable:

  • Change drawer icon back to back arrow - I successfully removed the drawer icon, but in place there's.... nothing. No up caret, no back button, no icon. I suspect this is because my Activity has no parent, but other than a cheap work around (create another Activity that acts as a parent which launches the main Activity), I'm at a lost of what to do.
  • Switching between Android Navigation Drawer image and Up caret when using fragments - Similar to the above, yet has far more detail. Ultimately, the icon still doesn't turn into a back button.
  • Android lollipop toolbar switch between open/close drawer and back button - I find this hard to follow, but ultimately the drawer icon can be tapped and does nothing (although I believe I know how to make it act as a back press). However, the icon doesn't change.

At the moment, I'm thinking of a long, arduous method of creating a custom icon that I hide and show (and hide/show the native drawer icon). However, is there a better way to switch between the drawer and back buttons?

As a side yet related question, I've been looking at the Material Design docs, and a few examples have an X in the top left corner. How different is that to implement than implementing the drawer vs back/up buttons?

Thanks~

Edit:

I can figure out how to replace the icon, but how would I get the click event?

So far, this was my best lead:

  • Cannot catch toolbar home button click event

What I've tried now:

  • Disabled the DrawerToggle when necessary (ie, mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);)
  • Added logs in onOptionsItemSelected in my NavigationDrawerFragment, my Activity, as well as the DialogFragment I'm currently testing which run if item.getItemId() == android.R.id.home is true. None of these log statements go off

For better context, I now have a full screen fragment which adds a "Save" button to the menu and changes the drawer icon to an "X". The fragment can get the save menu event, yet not even the Activity and Drawer can get when the X is tapped.

Edit2:

As requested, here is some code. Note that this is all from this Github repo, which I'm actively working on (note that I have a few useless functions here or there from rapid testing).

ActivityMain:

@Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      // Add the toolbar     mToolbar = (Toolbar) findViewById(R.id.toolbar);     if (mToolbar != null) {         setSupportActionBar(mToolbar);     }      // Initialize the drawer     mNavigationDrawerFragment = (NavigationDrawerFragment)             getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);      // Set up the drawer     mNavigationDrawerFragment.setUp(             R.id.navigation_drawer,             (DrawerLayout) findViewById(R.id.drawer_layout),             mToolbar);      // TODO: Check if this helps to catch the main toolbar button click     getSupportActionBar().setDisplayShowHomeEnabled(true);      // Get the titles for the Toolbar     mTitles = getResources().getStringArray(R.array.drawer_items);      mDrawerPosition = -1;     if (savedInstanceState == null) {         // If there was no saved position, then the default, starting position should be used         forceChangeItemSelected(0);     }     else {         // Otherwise, get the saved position from the bundle         int position = savedInstanceState.getInt(KEY_DRAWERPOS);         mNavigationDrawerFragment.setSelectedItem(position);         // Title needs to be re-set         getSupportActionBar().setTitle(mTitles[position]);     }      // If I include the below bit, then the DrawerToggle doesn't function         // I don't know how to switch it back and forth     mToolbar.setNavigationOnClickListener(new View.OnClickListener() {         @Override         public void onClick(View v) {             Log.d(LOG_TAG, "Navigation was clicked");          }     }); }  @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.     Log.d(LOG_TAG, "Activity responding to menu click...");     if(item.getItemId() == android.R.id.home) Log.d(LOG_TAG, "Activity got it....");      // If the fragment is supposed to handle things, then let it     if(mIsFragmentHandlingMenus) return false;      int id = item.getItemId();     if(id == R.id.save) {         // This isn't implemented! If chosen, then there's a bug!         Log.e(LOG_TAG, "onOptionsItemSelected: Save was selected!");     }      return super.onOptionsItemSelected(item); }  @Override public void fragmentHandlingMenus(boolean isFragmentHandlingMenus) {     // Simply store the setting     mIsFragmentHandlingMenus = isFragmentHandlingMenus;      // Toggle the drawer as necessary     mNavigationDrawerFragment.toggleDrawerUse(!isFragmentHandlingMenus); } 

NavigationDrawerFragment:

public void toggleDrawerUse(boolean useDrawer) {     // Enable/Disable the icon being used by the drawer     mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);      // TODO: Enable/Disable the drawer even being able to open/close }  @Override public boolean onOptionsItemSelected(MenuItem item) {     Log.d(LOGTAG, "Drawer responding to menu click...");     if(item.getItemId() == android.R.id.home) Log.d(LOGTAG, "Drawer got it....");     if (mDrawerToggle.onOptionsItemSelected(item)) {         return true;     }      return super.onOptionsItemSelected(item); } 

GoalAdderFragment:

@Override public void onActivityCreated(Bundle savedInstanceState) {     super.onActivityCreated(savedInstanceState);     // Allow this fragment to handle toolbar menu items     setHasOptionsMenu(true);      // Set up the toolbar     ((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);     ((ActionBarActivity) getActivity()).getSupportActionBar().setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel);     ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(getResources().getString(R.string.title_addgoal)); }  @Override public void onAttach(Activity activity) {     super.onAttach(activity);      // Cache the Activity as the frag handler if necessary     if(mFragHandler == null)         mFragHandler = (TransactionHandler.FragmentTransactionHandler) getActivity();     // Tell the Activity to let fragments handle the menu events     mFragHandler.fragmentHandlingMenus(true); }  @Override public void onDetach() {     super.onDetach();      // Tell the Activity that it can now handle menu events once again     mFragHandler.fragmentHandlingMenus(false); }  @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {     inflater.inflate(R.menu.save_menu, menu); }  @Override public boolean onOptionsItemSelected(MenuItem item) {     Log.d(LOGTAG, "Item id: " + item.getItemId() + " | Save id: " + R.id.save);     Toast.makeText(getActivity(), "Fragment activated!", Toast.LENGTH_SHORT).show();      switch (item.getItemId()) {         case R.id.save:             return true;         case android.R.id.home:             return true;         default:             break;     }      return false; } 

Solution:

This is the ultimate solution I ended up on, with the help of natario's answer below:

NavigationDrawerFragment:

private View.OnClickListener mOriginalListener;  public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {      /* Rest of setting up code */       // Save the default listener after setting everything else up      mOriginalListener = mDrawerToggle.getToolbarNavigationClickListener(); }  // Tells the toolbar+drawer to switch to the up button or switch back to the normal drawer public void toggleDrawerUse(boolean useDrawer) {     // Enable/Disable the icon being used by the drawer     mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);      // Switch between the listeners as necessary     if(useDrawer)         mDrawerToggle.setToolbarNavigationClickListener(mOriginalListener);     else         mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {             @Override             public void onClick(View v) {                 Toast.makeText(getActivity(), "Custom listener", Toast.LENGTH_SHORT).show();             }         }); } 
like image 218
Jawad Avatar asked Feb 15 '15 21:02

Jawad


People also ask

How do I change the Back button on my toolbar?

Customize Back Button in Action Bar We can easily Customize the Back Button by using the getSupportActionBar() library and setting the drawable file using setHomeAsUpIndicator in the java/kotlin file. actionBar. setHomeAsUpIndicator(R. drawable.


1 Answers

Put this code into onCreate() of your Activity. Works well for me. Even using compileSdk 23 and higher.

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);     final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);     if(toolbar != null) {         toggle = new ActionBarDrawerToggle(                 this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);         toggle.syncState();         drawer.setDrawerListener(toggle);         getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {             @Override             public void onBackStackChanged() {                 if (getSupportFragmentManager().getBackStackEntryCount() > 0) {                     getSupportActionBar().setDisplayHomeAsUpEnabled(true); // show back button                     toolbar.setNavigationOnClickListener(new View.OnClickListener() {                         @Override                         public void onClick(View v) {                             onBackPressed();                         }                     });                 } else {                     //show hamburger                     getSupportActionBar().setDisplayHomeAsUpEnabled(false);                     toggle.syncState();                     toolbar.setNavigationOnClickListener(new View.OnClickListener() {                         @Override                         public void onClick(View v) {                             drawer.openDrawer(GravityCompat.START);                         }                     });                 }             }         }); 
like image 70
matusalem Avatar answered Oct 11 '22 13:10

matusalem