I have this nav drawer which was working perfectly fine.
Refactoring my code I removed all onOptionsItemSelecteds in activities and made all activities inherit from a base activity which extends AppComplatActivity and implements all the necessary methods.
After this clicking on hamburger icon does not work any more even though I have syncstate() and every thing.
Any clues why this is not working?
One of the activities:
public class MainActivity extends BaseActivity implements SearchFilterFragment.OnFragmentInteractionListener {
NavigationView navigationView;
DrawerLayout drawerLayout;
private Tracker mTracker;
#Override
protected void onResume() {
super.onResume();
drawerLayout.openDrawer(GravityCompat.START);
}
#Override
protected void onPostResume() {
super.onPostResume();
mTracker.setScreenName("MainActivity" + "-----");
mTracker.send(new HitBuilders.ScreenViewBuilder().build());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.openDrawer(GravityCompat.START);
navigationView = (NavigationView) findViewById(R.id.navigation_view_primary);
navigationView.setNavigationItemSelectedListener(new NavigationDrawerListener(this));
setupToolbar();
Haftdong application = (Haftdong) getApplication();
mTracker = application.getDefaultTracker();
}
private void setupToolbar() {
// Show menu icon
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);// will make the icon clickable and add the < at the left of the icon.
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();//for hamburger icon
}
#Override
public void onFragmentInteraction(Uri uri) {
}
}
BaseActivity:
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_base, menu);
return true;
}
#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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
You're using the four-parameter constructor for ActionBarDrawerToggle, which means you'll have to call the toggle's onOptionsItemSelected() method in MainActivity's onOptionsItemSelected() override in order to open/close the drawer.
For example:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
If you happen to be providing your own Toolbar – e.g., as the support ActionBar (though it's not necessary to set it as such) – then you can instead pass that Toolbar as the third argument in the ActionBarDrawerToggle constructor call. For example:
Toolbar toolbar = findViewById(R.id.toolbar);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
The drawer opening/closing will then be handled by ActionBarDrawerToggle internally, and you won't need to call through to the toggle in onOptionsItemSelected().
The setDisplayHomeAsUpEnabled() call is also unnecessary for this setup, which is handy if you don't want to set the Toolbar as the ActionBar.
I have this nav drawer which was working perfectly fine.
Refactoring my code I removed all onOptionsItemSelecteds in activities and made all activities inherit from a base activity which extends AppComplatActivity and implements all the necessary methods.
After this clicking on hamburger icon does not work any more even though I have syncstate() and every thing.
Any clues why this is not working?
One of the activities:
public class MainActivity extends BaseActivity implements SearchFilterFragment.OnFragmentInteractionListener {
NavigationView navigationView;
DrawerLayout drawerLayout;
private Tracker mTracker;
#Override
protected void onResume() {
super.onResume();
drawerLayout.openDrawer(GravityCompat.START);
}
#Override
protected void onPostResume() {
super.onPostResume();
mTracker.setScreenName("MainActivity" + "-----");
mTracker.send(new HitBuilders.ScreenViewBuilder().build());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.openDrawer(GravityCompat.START);
navigationView = (NavigationView) findViewById(R.id.navigation_view_primary);
navigationView.setNavigationItemSelectedListener(new NavigationDrawerListener(this));
setupToolbar();
Haftdong application = (Haftdong) getApplication();
mTracker = application.getDefaultTracker();
}
private void setupToolbar() {
// Show menu icon
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);// will make the icon clickable and add the < at the left of the icon.
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();//for hamburger icon
}
#Override
public void onFragmentInteraction(Uri uri) {
}
}
BaseActivity:
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_base, menu);
return true;
}
#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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
You're using the four-parameter constructor for ActionBarDrawerToggle, which means you'll have to call the toggle's onOptionsItemSelected() method in MainActivity's onOptionsItemSelected() override in order to open/close the drawer.
For example:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
If you happen to be providing your own Toolbar – e.g., as the support ActionBar (though it's not necessary to set it as such) – then you can instead pass that Toolbar as the third argument in the ActionBarDrawerToggle constructor call. For example:
Toolbar toolbar = findViewById(R.id.toolbar);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
The drawer opening/closing will then be handled by ActionBarDrawerToggle internally, and you won't need to call through to the toggle in onOptionsItemSelected().
The setDisplayHomeAsUpEnabled() call is also unnecessary for this setup, which is handy if you don't want to set the Toolbar as the ActionBar.
I'm using the v7.widget.Toolbar in my app, but I'm getting some funky functionality. I have my main activity and fragments that are placed over it. When there are no fragments on the backStack, the hamburger button shows and the menu works correctly. When I add a fragment to the backStack, the up caret shows correctly, however when I click the up caret, the nav menu opens instead of the fragment being popped off the stack.
Now if there's a real answer, I'll take it, but at this point I will take a hackish solution. I tried adding a listener so I knew when the action bar button was hit, but that just made it so the fragment popped, the page went back, but the nav menu still opened. onOptionsItemSelected is not being called (due to the way I implemented the Drawer Toggle, but doing it the "correct" way gave me way more problems, such as no nav menu showing on the main page at all).
To sum it up for clarity: The up caret is opening the nav menu, instead of going back.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = getTitle();
toolbar = (Toolbar) findViewById(R.id.tool_bar); // Attaching the layout to the toolbar object
frameLayout = (FrameLayout) findViewById(R.id.frame_layout);
setSupportActionBar(toolbar);
//Listen for changes in the back stack
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
shouldDisplayHomeUp();
}
});
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerContent = findViewById(R.id.drawer_content);
mDrawerList = (ListView) findViewById(R.id.drawer_list);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerList.setAdapter(new DrawerListItemAdapter(DRAWER_ITEMS, getApplicationContext()));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.openDrawer, R.string.closeDrawer) {
public void onDrawerClosed(View view) {
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
Log.d("Main", "Open Menu");
}
};
mDrawerToggle.syncState();
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
#Override
public void onBackStackChanged() {
shouldDisplayHomeUp();
}
public void shouldDisplayHomeUp(){
//Enable Up button only if there are entries in the back stack
boolean canback = getSupportFragmentManager().getBackStackEntryCount()>0;
ActionBar ab = getSupportActionBar();
if(ab != null){
ab.setDisplayHomeAsUpEnabled(canback);
}
if(!canback){
//App can crash as mDrawerToggle will be null when app launches
try{
mDrawerToggle.syncState();
}catch (Exception e){
e.printStackTrace();
}
}
Log.d("Main", "shouldDisplayHomeUp");
}
#Override
public boolean onSupportNavigateUp() {
//This method is called when the up button is pressed. Just the pop back stack.
Log.d("Main", "Up carat pressed");
getSupportFragmentManager().popBackStack();
return true;
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
Log.d("Main", "Menu item clicked: " + Integer.toString(item.getItemId()));
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
The solution that worked for me
A combination of Alex' answer (including his comment in the answer) below and this hacky answer.
You can use setToolbarNavigationClickListener() - it sets the listener that handles clicks when drawer indicator is disabled
drawerToggle.setToolbarNavigationClickListener((View view) -> {
getSupportFragmentManager().popBackStack();
});
Currently Used Google Navigation Drawer, having some problem when user backpress.
When user backpress, they didn't update menu Item
Example When I click the App. The sequence are A>B>C>B>C ,if I backpress I wanted to be C>B>A. How should I code this way out ?
My code
public class MainActivity extends AppCompatActivity {
private String appTitle;
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private TextView toolbarTitle;
private Fragment fragment;
private FragmentManager fragmentManager;
private Title title;
private MenuItem menuItem2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbarTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
toolbarTitle.setTextColor(Color.parseColor("#FFFFFF"));
setTitle("");
fragmentManager = getSupportFragmentManager();
fragment= new HomeFragment();
title = new Title(getApplicationContext());
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment , title.getStrHome()).commit();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem2 = menuItem;
menuItem.setChecked(true);
drawerLayout.closeDrawers();
if (menuItem.getItemId() == R.id.nav_home) {
fragment = new HomeFragment();
appTitle = title.getStrHome();
} else if ((menuItem.getItemId() == R.id.nav_direction)) {
fragment = new DirectionFragment();
appTitle = title.getStrDirection();
} else if ((menuItem.getItemId() == R.id.nav_more)) {
fragment = new MoreFragment();
appTitle = title.getStrMore();
} else if((menuItem.getItemId()==R.id.nav_directory)){
fragment = new DirectoryFragment();
appTitle = title.getStrDirectory();
}
else {
Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
}
replaceFragment(fragment,appTitle);
return true;
}
});
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle =
new ActionBarDrawerToggle
(this,drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_close){
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
drawerLayout.setDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
}
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(GravityCompat.START)){
drawerLayout.closeDrawer(GravityCompat.START);
}
else {
if (fragmentManager.getBackStackEntryCount() > 0 ){
fragmentManager.popBackStack();
toolbarTitle.setText(appTitle);
menuItem2.setChecked(true);
} else {
finish();
}
}
}
public void replaceFragment(Fragment fragment, String tag){
toolbarTitle.setText(tag);
FragmentTransaction ft = fragmentManager.beginTransaction().replace(R.id.content_frame, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
As stated on the official page on Android tasks and back stack you can see how you can accomplish your desired behaviour using the FLAG_ACTIVITY_CLEAR_TOP in your Intent flags. This picture demonstrates it very well.
Your regular back button proceeds as:
When you specify this flag, you get a behavior like you need
Edit:
The official documentation states:
FLAG_ACTIVITY_CLEAR_TOP
If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the
other activities on top of it are destroyed
This means, there will be no duplicates of your different Activities, and you will have a clean Back Stack.
In your example A>B>C>B>C would not be possible. Instead it would be A>B>C, since B and C already exist in the stack, they will not be added, but replaced instead.
Study the Android Activity Launch Mode.
here is the clear Explanation available.
Just take a look.
I've implemented the newest appcompat library and using the Toolbar as action bar. But the problem is I cannot catch the home button / hamburger icon click event. I've tried and looked everything but doesn't seem to find a similar problem.
This is my Activity class :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the drawer.
navDrawerFragment =
(NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
navDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout),
toolbar);
}
And this is my NavigationDrawerFragment class :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentSelectedPosition = savedInstanceState.getInt(
STATE_SELECTED_POSITION);
fromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(currentSelectedPosition);
}
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like
// to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
drawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
drawerListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
selectItem(position);
}
});
//mDrawerListView.setAdapter();
//mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return drawerListView;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
fragmentContainerView = getActivity().findViewById(fragmentId);
this.drawerLayout = drawerLayout;
// set a custom shadow that overlays the main
// content when the drawer opens
drawerLayout.setDrawerShadow(
R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view
// with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
drawerToggle = new ActionBarDrawerToggle(
getActivity(),
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
// If the user hasn't 'learned' about the drawer,
// open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!userLearnedDrawer && !fromSavedInstanceState) {
drawerLayout.openDrawer(fragmentContainerView);
}
// Defer code dependent on restoration of previous instance state.
drawerLayout.post(new Runnable() {
#Override
public void run() {
drawerToggle.syncState();
}
});
drawerLayout.setDrawerListener(drawerToggle);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
drawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("cek", "item selected");
if (drawerToggle.onOptionsItemSelected(item)) {
Log.d("cek", "home selected");
return true;
}
return super.onOptionsItemSelected(item);
}
when I clicked a menu item, the log "item selected" gets called. But when I click on the home button, it opens navigation drawer but the log "home selected" never get called. I've set onOptionsItemSelected method inside my Activity as well, but it still doesn't get called.
If you want to know when home is clicked is an AppCompatActivity then you should try it like this:
First tell Android you want to use your Toolbar as your ActionBar:
setSupportActionBar(toolbar);
Then set Home to be displayed via setDisplayShowHomeEnabled like this:
getSupportActionBar().setDisplayShowHomeEnabled(true);
Finally listen for click events on android.R.id.home like usual:
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
Timber.d("Home pressed");
}
return super.onOptionsItemSelected(menuItem);
}
If you want to know when the navigation button is clicked on a Toolbar in a class other than AppCompatActivity you can use these methods to set a navigation icon and listen for click events on it. The navigation icon will appear on the left side of your Toolbar where the the "home" button used to be.
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("cek", "home selected");
}
});
If you want to know when the hamburger is clicked and when the drawer opens, you're already listening for these events via onDrawerOpened and onDrawerClosed so you'll want to see if those callbacks fit your requirements.
mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// event when click home button
}
});
in mycase this code work perfect
This is how I do it to return to the right fragment otherwise if you have several fragments on the same level it would return to the first one if you don´t override the toolbar back button behavior.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
I think the correct solution with support library 21 is the following
// action_bar is def resource of appcompat;
// if you have not provided your own toolbar I mean
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
// change home icon if you wish
toolbar.setLogo(this.getResValues().homeIconDrawable());
toolbar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//catch here title and home icon click
}
});
}
I have handled back and Home button in Navigation Drawer like
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerLayout;
NavigationView navigationView;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
resetActionBar();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
//showing first fragment on Start
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//listener for home
if(id==android.R.id.home)
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
onBackPressed();
else
drawerLayout.openDrawer(navigationView);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Begin the transaction
Fragment fragment = null;
// Handle navigation view item clicks here.
int id = item.getItemId();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (id == R.id.nav_companies_list) {
fragment = new FirstFragment();
// Handle the action
}
// Begin the transaction
if(fragment!=null){
if(item.isChecked()){
if(getSupportFragmentManager().getBackStackEntryCount()==0){
drawer.closeDrawers();
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}
return true;
}
public void removeAllFragments(){
getSupportFragmentManager().popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void replaceFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.replace(R.id.WikiCompany, fragment).addToBackStack("")
.commit();
}
public void updateDrawerIcon() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try {
Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
drawerToggle.setDrawerIndicatorEnabled(false);
else
drawerToggle.setDrawerIndicatorEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 50);
}
public void resetActionBar()
{
//display home
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
and In each onViewCreated I call
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((HomeActivity)getActivity()).updateDrawerIcon();
((HomeActivity) getActivity()).setActionBarTitle("List");
}
This is how I implemented it pre-material design and it seems to still work now I've switched to the new Toolbar. In my case I want to log the user in if they attempt to open the side nav while logged out, (and catch the event so the side nav won't open). In your case you could not return true;.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isLoggedIn() && item.getItemId() == android.R.id.home) {
login();
return true;
}
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
I changed the DrawerLayout a bit to get the events and be able to consume and event, such as if you want to use the actionToggle as back if you are in detail view:
public class ListenableDrawerLayout extends DrawerLayout {
private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
private boolean mManualCall;
public ListenableDrawerLayout(Context context) {
super(context);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets the listener for the toggle button
*
* #param mOnToggleButtonClickedListener
*/
public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
}
/**
* Opens the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal openDrawer method
*
* #param drawerView
*/
public void openDrawerManual(View drawerView) {
mManualCall = true;
openDrawer(drawerView);
}
/**
* Closes the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal closeDrawer method
*
* #param drawerView
*/
public void closeDrawerManual(View drawerView) {
mManualCall = true;
closeDrawer(drawerView);
}
#Override
public void openDrawer(View drawerView) {
// Check for listener and for not manual open
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.openDrawer(drawerView);
}
#Override
public void closeDrawer(View drawerView) {
// Check for listener and for not manual close
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.closeDrawer(drawerView);
}
/**
* Interface for toggle button callbacks
*/
public static interface OnToggleButtonClickedListener {
/**
* The ActionBarDrawerToggle has been pressed in order to open the drawer
*
* #return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleOpenDrawer();
/**
* The ActionBarDrawerToggle has been pressed in order to close the drawer
*
* #return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleCloseDrawer();
}
}
The easiest approach we could do is change the home icon to a known icon and compare drawables (because android.R.id.home icon can differ to different api versions
so set a toolbar as actionbar
SetSupportActionBar(_toolbar);
_toolbar.NavigationIcon = your_known_drawable_here;
for (int i = 0; i < _toolbar.ChildCount; i++)
{
View v = _toolbar.GetChildAt(i);
if (v is ImageButton)
{
ImageButton imageButton = v as ImageButton;
if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
{
//here v is the widget that contains the home icon you can add your click events here
}
}
}
In my case I had to put the icon using:
toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
And then listen to click events with default onOptionsItemSelected and android.R.id.home id
For anyone looking for a Xamarin implementation (since events are done differently in C#), I simply created this NavClickHandler class as follows:
public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
private Activity mActivity;
public NavClickHandler(Activity activity)
{
this.mActivity = activity;
}
public void OnClick(View v)
{
DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
if (drawer.IsDrawerOpen(GravityCompat.Start))
{
drawer.CloseDrawer(GravityCompat.Start);
}
else
{
drawer.OpenDrawer(GravityCompat.Start);
}
}
}
Then, assigned a custom hamburger menu button like this:
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
this.drawerToggle.DrawerIndicatorEnabled = false;
this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);
And finally, assigned the drawer menu toggler a ToolbarNavigationClickListener of the class type I created earlier:
this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);
And then you've got a custom menu button, with click events handled.
Try this code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
//You can get
}
return super.onOptionsItemSelected(item);
}
Add below code to your onCreate() metod
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
Apart from the answer provided by MrEngineer13, there is also another possible reason why the click event might not have been captured in the onOptionsSelected method. Your DrawerLayout may have overlayed your Toolbar's interface component in the layout XML file. Therefore, whenever you attempt to click the Home button, you're only clicking the DrawerLayout, but not the Home button that's located beneath it.
All you have to do now is rearrange your Toolbar in the corresponding layout XML file so that it is not blocked by any other UI component.
Programmatically, I did attempt to call the bringToFront() method on the toolbar (toolbar.bringToFront()). However, in my app's context, it does not seem to be the solution.