NavigationView slow to open / Skipping frames (Android Design Lib) - android

I'm using a NavigationView supplied by the Android Design Library. I've found after adding a few items to it that is performing quite poorly. On first launch it takes a second or so to open for the firs time. Here's a screenshot of the UI.
I'll try to post some of the relevant bits of code.
Drawer XML
<group android:checkableBehavior="single">
<item
android:id="#+id/home"
android:checked="false"
android:icon="#drawable/ic_home"
android:title="Home" />
<item
android:id="#+id/about"
android:checked="false"
android:icon="#drawable/ic_about"
android:title="About" />
<item
android:id="#+id/gallery"
android:checked="false"
android:icon="#drawable/ic_gallery"
android:title="Gallery" />
<item
android:id="#+id/settings"
android:icon="#drawable/ic_action_settings"
android:title="Settings" />
<item
android:id="#+id/navigation_subheader"
android:title="Categories">
<menu>
<item
android:id="#+id/science"
android:checked="false"
android:icon="#drawable/ic_science"
android:title="Science" />
<item
android:id="#+id/parenting"
android:checked="false"
android:icon="#drawable/ic_parenting"
android:title="Parenting" />
<item
android:id="#+id/android"
android:checked="false"
android:icon="#drawable/ic_android"
android:title="Android" />
<item
android:id="#+id/technology"
android:checked="false"
android:icon="#drawable/ic_tech"
android:title="Technology" />
<item
android:title=""
android:checkable="false"
android:visible="false"
android:orderInCategory="200"/>
</menu>
</item>
</group>
MainAct
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initializing Toolbar and setting it as the actionbar
toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
//Initializing NavigationView
navigationView = (NavigationView) findViewById(R.id.navigation_view);
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
Log.v(TAG + "-S", "Pre_Switch = " + mCurCheckPosition);
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
case R.id.home:
homeFragment();
return true;
case R.id.about:
webFragment();
return true;
case R.id.gallery:
galleryFragment();
return true;
case R.id.science:
scienceFragment();
return true;
case R.id.parenting:
parentingFragment();
return true;
case R.id.android:
androidFragment();
return true;
case R.id.technology:
technologyFragment();
return true;
case R.id.settings:
Intent i = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(i);
default:
return true;
}
}
});
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.openDrawer, R.string.closeDrawer){
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawerLayout.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessay or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
And finally here is the error im seeing in the logs from the Choreographer, i'm hoping this is just a bug in the lib however im wondering if someone else came across this and might have a work around.
I/Choreographer﹕ Skipped 117 frames! The application may be doing too much work on its main thread.
Full source is available here: https://github.com/caman9119/The_Jones_Theory

Found the issue in my header.xml I was using a background.png that was 1080x720p. I scaled the image down to ~400x300 and voila, interesting problem indeed.

If you are using dynamic images for the background (using user facebook or g+ banner by example) and using Picasso this piece of code can be usefull:
ImageView background = (ImageView) findViewById(R.id.background);
Picasso
.with(context)
.load([Your image source here])
.fit()
.centerCrop()
.into(background)

Had the same problem, i was using 512 x 512 images in the drawer list. All images were initially placed in the 'drawable' folder but when i moved them to the 'drawable-xxhdpi' folder, it was butter smooth.

Related

NavigationView item selector does not highlight the enabled item

I'm trying to change the text color of the selected item in the NavigationView. Using the information for the previous topic I set a selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/primaryColor" android:state_checked="true" />
<item android:color="#color/lightGrayColor" android:state_checked="false" />
</selector>
The primaryColor is blue. The NavigationView is as follows:
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/activity_nav_header"
app:menu="#menu/nev_menu"
app:itemIconTint="#drawable/menu_item_selector"
app:itemTextColor="#drawable/menu_item_selector" />
</androidx.drawerlayout.widget.DrawerLayout>
As you can see I set app:itemTextColor to menu_item_selector. But when I run the application, I see the selected item as grey. How does the NavigationView know which screen am I seeing right now? How do I fix it?
I'm using onNavigationItemSelected to switch between activities. Also I currently have only two windows - the dashboard and the logout. From the main screen I move to the dashboard (which contains the menu) and using the logout I go back to the main screen. Maybe the reason for it not working is because it does not know that the current screen is dashboard?
The dashboard java cotnains the following method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
toolBar = findViewById(R.id.toolbar);
setSupportActionBar(toolBar);
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolBar,
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View hView = navigationView.getHeaderView(0);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.dashboard:
// CURRENT ACTIVITY
break;
case R.id.messages:
startActivity(new Intent(this, MessagesActivity.class));
break;
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
case R.id.about:
startActivity(new Intent(this, AboutActivity.class));
break;
case R.id.logout:
startActivity(new Intent(this, MainActivity.class));
break;
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
For the initial look, you set a checked color to primaryColor, but overwrite it with lightGrayColor as you didn't specify the state that this color is available at; so you need to specify the state by android:state_checked="false"
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/primaryColor" android:state_checked="true" />
<item android:color="#color/lightGrayColor" android:state_checked="false"/>
</selector>
You can also set the default selected item at the app start by trying any of:
navigationView.getMenu().getItem(0).setChecked(true);
navigationView.setCheckedItem(R.id.nav_item);
Update
This is how it works with me
Step 1: Use the same selector:
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/primaryColor" android:state_checked="true" />
<item android:color="#color/lightGrayColor" android:state_checked="false" />
</selector>
Step 2: use the xml attribute app:itemTextColor within NavigationView widget
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/navigation_header_layout"
app:itemTextColor="#drawable/selector"
app:menu="#menu/navigation_menu" />
Step 3:
The previous step attribute won't work automatically as for some reason when you hit an item from the NavigationView menu, it doesn't consider this as a button check. So you need to manually get the selected item checked and clear the previously selected item. Use below listener to do that
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
// remove all colors of the items to the `unchecked` state of the selector
removeColor(mNavigationView);
// check the selected item to change its color set by the `checked` state of the selector
item.setChecked(true);
switch (item.getItemId()) {
case R.id.dashboard:
// CURRENT ACTIVITY
break;
case R.id.messages:
startActivity(new Intent(this, MessagesActivity.class));
break;
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
case R.id.about:
startActivity(new Intent(this, AboutActivity.class));
break;
case R.id.logout:
startActivity(new Intent(this, MainActivity.class));
break;
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
private void removeColor(NavigationView view) {
for (int i = 0; i < view.getMenu().size(); i++) {
MenuItem item = view.getMenu().getItem(i);
item.setChecked(false);
}
}
Now the text color will change perfectly.
Step 4:
To change icon colors, use the app:iconTint attribute in the NavigationView menu items, and set to the same selector.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/nav_account"
android:checked="true"
android:icon="#drawable/ic_person_black_24dp"
android:title="My Account"
app:iconTint="#drawable/selector" />
<item
android:id="#+id/nav_settings"
android:icon="#drawable/ic_settings_black_24dp"
android:title="Settings"
app:iconTint="#drawable/selector" />
<item
android:id="#+id/nav_logout"
android:icon="#drawable/logout"
android:title="Log Out"
app:iconTint="#drawable/selector" />
</menu>
Result:

How to change the Background color of selected item in the Navigation Drawer

I was working on Nav drawer on my app.
I have made the background of my nav drawer #000000(Black). Whenever I select any item the textcolor of text changes from #E44F50(Carrot Red) to black but I cant change the background color of the selected item.
All I want is to change the background color of selected Item from black to carrot red.
Here is the github link to my app-
https://github.com/manmeet-22/NewsSnips-app.git
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/colorPrimary"
app:headerLayout="#layout/header"
app:itemIconTint="#drawable/drawer_item" //changing text color
app:itemTextAppearance="#style/TextAppearance20"
app:itemTextColor="#color/drawer_item"
app:itemBackground="#drawable/drawer_selected_item" //trying to change backgroundcolor the same way
app:menu="#menu/drawer"
tools:context="com.androidexample.newssnips.app.NavigationDrawerFragment"/>
</android.support.v4.widget.DrawerLayout>
In this I tried changing the background color like I did for the text but my app crashes.
here is my drawer_selected_item.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/colorAccent" android:state_selected="true"/>
<item android:color="#android:color/transparent"/>
</selector>
here is my drawer_item.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/colorPrimary" android:state_checked="true" />
<item android:color="#color/colorAccent" />
</selector>
Here is my MainActivity.java:
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setItemIconTintList(null);
Menu menu = navigationView.getMenu();
//For chnaging the textColor and textSize of group's Name ie. Category
MenuItem categoryName= menu.findItem(R.id.categoryGroup);
SpannableString s = new SpannableString(categoryName.getTitle());
s.setSpan(new TextAppearanceSpan(this, R.style.TextAppearance25), 0, s.length(), 0);
//For changing the Text of action bar as the selected category
categoryName.setTitle(s);
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked())
menuItem.setChecked(false);
else
menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was being clicked and open the Appopriate news accordingly
switch (menuItem.getItemId()) {
case R.id.itemWorld:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=world";
setTitle("World News");
basicDefaults();
return true;
case R.id.itemFootball:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=football";
setTitle("Football News");
basicDefaults();
return true;
case R.id.itemFashion:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=fashion";
setTitle("Fashion News");
basicDefaults();
return true;
case R.id.itemSports:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=sport";
setTitle("Sports News");
basicDefaults();
return true;
case R.id.itemBusiness:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=business";
setTitle("Business News");
basicDefaults();
return true;
case R.id.itemTechnology:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=technology";
setTitle("Technology News");
basicDefaults();
return true;
case R.id.itemOpinion:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=commentisfree";
setTitle("Opinions");
basicDefaults();
return true;
case R.id.itemCulture:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=culture";
setTitle("Culture News");
basicDefaults();
return true;
case R.id.itemTravel:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=travel";
setTitle("Travel News");
basicDefaults();
return true;
case R.id.itemLifestyle:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=lifeandstyle";
setTitle("LifeStyle News");
basicDefaults();
return true;
case R.id.itemEnvironment:
GAURDIAN_REQUEST_URL = "http://content.guardianapis.com/search?api-key=f51fa87d-8a55-4fc1-b552-8fa6eb98dee4&section=environment";
setTitle("Environment News");
basicDefaults();
return true;
default:
Toast.makeText(getApplicationContext(), "Somethings Wrong", Toast.LENGTH_SHORT).show();
return true;
}
}
});
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.openDrawer, R.string.closeDrawer) {
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//calling sync state is necessay or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
PS.- I have tried implementing other methods too like
adding this in apptheme in styles.xml file.
<item name="android:activatedBackgroundIndicator">#drawable/drawer_selected_item</item>
But still I cant find my solution.
Please help it is the last thing that is left in my project.
I have got the solution-
In the NavigationView I did-
app:itemBackground="#drawable/drawer_selected_item"
Thus my NavigationView looks like-
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/colorPrimary"
app:headerLayout="#layout/header"
app:itemIconTint="#drawable/drawer_item"
app:itemTextAppearance="#style/TextAppearance20"
app:itemTextColor="#drawable/drawer_item"
app:menu="#menu/drawer"
app:itemBackground="#drawable/drawer_selected_item"
tools:context="com.androidexample.newssnips.app.NavigationDrawerFragment" />
In the drawer_selected_item I modified file as-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#color/colorAccent"/>
<item android:drawable="#android:color/transparent" />
</selector>
NavigationView has a method called setItemTextColor(). It uses a ColorStateList.navigationView.setItemTextColor(). with ColorStateList as a parameter.
Adding explanation to Caspian's answer:
Android Developers Documentation provides ColorStateList so you can play around on different states of a View in android.
Example Code here: ColorStateList Android Example

onNavigationItemSelected not working in NavigationView

Please can someone help me with fragments from the navigation drawer, for some reason I can't get them to work and all the code looks right.
Here is the link to the source code.
Use this code:
navigationView = (NavigationView) findViewById(R.id.navigationView);
navigationView.bringToFront();
Have a look at your MainActivity.java.
You have implemented the callbacks for NavigationView.OnNavigationItemSelectedListener in MainActivity as below,
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// blah blah
}
Also check the setupDrawerContent method.
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
drawerLayout.closeDrawers();
return true;
}
});
}
In this method you are creating a local OnNavigationItemSelectedListener.
So you are not using the OnNavigationItemSelectedListener that you have overridden in MainActivity.
The solution is to use this as argument for setNavigationItemSelectedListener. By doing this all your clicks will go the onNavigationItemSelected of MainActivity rather than going to the local onNavigationItemSelected.
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(this);
}
Also move the code in the local onNavigationItemSelected to the onNavigationItemSelected of MainActivity.
So your onNavigationItemSelected will be something like this,
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// Handle navigation view item clicks here.
int id = menuItem.getItemId();
menuItem.setChecked(true);
drawerLayout.closeDrawers();
if (id == R.id.nav_home) {
// Handle the home action
Toast.makeText(this, "Home", Toast.LENGTH_SHORT).show();
} else if (id == R.id.nav_the_wetlands) {
Toast.makeText(this, "The Wetlands", Toast.LENGTH_SHORT).show();
TheWetlandsFragment theWetlandsFragment = new TheWetlandsFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.relativelayout_for_fragment, theWetlandsFragment, theWetlandsFragment.getTag()).commit();
} else if (id == R.id.nav_the_mistbelt_forests) {
Toast.makeText(this, "The Mistbelt Forests", Toast.LENGTH_SHORT).show();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Also change your activity_main_drawer_view.xml as follows to solve the multiple selection issue you have in the Navigation Drawer,
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_dashboard"
android:title="Home" />
</group>
<item android:title="Information">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_the_wetlands"
android:icon="#drawable/ic_event"
android:title="The Wetlands" />
<item
android:id="#+id/nav_the_mistbelt_forests"
android:icon="#drawable/ic_event"
android:title="The Mistbelt Forests" />
<item
android:id="#+id/nav_the_grasslands"
android:icon="#drawable/ic_event"
android:title="The Grasslands" />
</group>
</item>
<item android:title="Quick Go To">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_accommodation"
android:icon="#drawable/ic_event"
android:title="Accommodation" />
<item
android:id="#+id/nav_cuisine"
android:icon="#drawable/ic_forum"
android:title="Cuisine" />
<item
android:id="#+id/nav_leisure_activites"
android:icon="#drawable/ic_forum"
android:title="Leisure & Activites" />
<item
android:id="#+id/nav_agri_tourism"
android:icon="#drawable/ic_forum"
android:title="Agri-tourism" />
<item
android:id="#+id/nav_education"
android:icon="#drawable/ic_forum"
android:title="Education" />
<item
android:id="#+id/nav_arts_crafts_decor"
android:icon="#drawable/ic_forum"
android:title="Arts, Crafts & DeCor" />
<item
android:id="#+id/nav_selective_shopping"
android:icon="#drawable/ic_forum"
android:title="Selective Shopping" />
<item
android:id="#+id/nav_for_children"
android:icon="#drawable/ic_forum"
android:title="For Children" />
</group>
</item>
<item android:title="Midlands Animals">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_midlands_birding_checklist"
android:icon="#drawable/ic_dashboard"
android:title="Midlands Birding Checklist" />
<item
android:id="#+id/nav_midlands_mammals_checklist"
android:icon="#drawable/ic_dashboard"
android:title="Midlands Mammals Checklist" />
</group>
</item>
</menu>
Good luck.
Don't use
NavigationUI.setupWithNavController(navigationView, navController);
instead of it do this
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Toast.makeText(MainActivity.this, "clicked", Toast.LENGTH_SHORT).show();
return false;
}
});
I have also faced the same problem some time back, and at the end i realized that i have not wrote the 2nd line of the following code
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
you make sure you have written the same otherwise your listener will not work
in my case i forgot to initialize navigation menu.
kindly follow following code:
public void initSideMenu() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
happy coding...
Make sure you have implement the interface NavigationView.OnNavigationItemSelectedListener.
Second point make sure to add these lines otherwise listnere will not be called.
navigationView=(NavigationView) findviewbyid(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
Add this line
navigationView.bringToFront();
Its works for me

I can't get multiple items to appear as selected in Navigation Drawer for Android

I'm building an Android app for the local bus system and I'm trying to use the navigation drawer to act as a filter for the routes that appear on the map. The functionality is there, but I'm struggling with the UI. Whenever I click on an item, everything else is set as unchecked, which is not what I want. I've been trying to find a solution for this issue, but didn't come up with anything. Here is the code for the navigation drawer:
MainActivity:
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// listen for navigation events
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
// set up the hamburger icon to open and close the drawer
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
final boolean enable;
//update highlighted item in the navigation menu
//menuItem.setChecked(!menuItem.isChecked());
if(menuItem.isChecked()){
menuItem.setChecked(false);
enable = false;
}
else{
menuItem.setChecked(true);
enable=true;
}
//menuItem.setChecked(true);
mNavItemId = menuItem.getItemId();
// allow some time after closing the drawer before performing real navigation
// so the user can see what is happening
// mDrawerLayout.closeDrawer(GravityCompat.START);
mDrawerActionHandler.postDelayed(new Runnable() {
#Override
public void run() {
navigate(menuItem.getItemId(),enable);
}
}, DRAWER_CLOSE_DELAY_MS);
return true;
}
and the layout file:
<item
android:id="#+id/filter_routes"
android:title="#string/filter">
<menu>
<group android:checkableBehavior="all">
<item
android:id="#+id/red_route"
android:title="#string/red_route"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:icon="#drawable/abc_btn_check_material"
android:checked="true"
android:checkable="true"/>
<item
android:id="#+id/blue_route"
android:title="#string/blue_route"
android:icon="#drawable/abc_btn_check_material"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:checked="true"
android:checkable="true"/>
<item
android:id="#+id/green_route"
android:title="#string/green_route"
android:icon="#drawable/abc_btn_check_material"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:checked="true"
android:checkable="true"/>
<item
android:id="#+id/orange_route"
android:title="#string/orange_route"
android:icon="#drawable/abc_btn_check_material"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:checked="true"
android:checkable="true"/>
<item
android:id="#+id/brown_route"
android:title="#string/brown_route"
android:icon="#drawable/abc_btn_check_material"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:checked="true"
android:checkable="true"/>
</group>
</menu>
</item>
I got multiple selections to work by returning false from onNavigationItemSelected(). From the Google docs for this return value of onNavigationItemSelected():
boolean true to display the item as the selected item
Apparently, this means that returning false leaves item selection in your control.
Here's an example.
XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="All">
<menu>
<group
android:checkableBehavior="all"
android:id="#+id/checkable_group"
>
<item
android:id="#+id/checkable_item_1"
android:title="A" />
<item
android:id="#+id/checkable_item_2"
android:title="B" />
<item
android:id="#+id/checkable_item_3"
android:title="C" />
<item
android:id="#+id/checkable_item_4"
android:title="D" />
</group>
</menu>
</item>
</menu>
Code:
#Override
public boolean onNavigationItemSelected(MenuItem item) {
if (item.isChecked()) {
item.setChecked(false);
}
else {
item.setChecked(true);
}
return false; // VERY Important to return false here
}
I submitted a bug report about this and it was closed as working as intended. Google apparently made NavigationView use menu XML with no intention of having it work like a menu.

NavigationView, multiple menus

I'm trying to use the NavigationView in one of my projects to implement a side menu. The app has two type of users: Admin and User.
I created the login activity and I log in as user or admin. I pass the name, email via intent (putExtra) to my NavigationActivity.
Since I have two type of users I created two type of menus (admin has more menu options).
I check the content of the passed value from the intent and inflate the navigation views menu accordingly.
My problem is I don't know how to separate in the listener the two type of menus. Should I create in my if else two listeners for each case? What would be the right approach? The way I did it doesn't work correctly, in my side menu I have the first two items from the user menu and after that the reamining items of the admin menu.
Here's thecode:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
Bundle extras = getIntent().getExtras();
String name = extras.getString("name");
String email = extras.getString("email");
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
if(name.equals("admin")){
// listener for admin here?
navigationView.inflateMenu(R.menu.admin_drawer);
}else{
// listener for user here?
navigationView.inflateMenu(R.menu.user_drawer);
}
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// questionable part here, doesn't work correctly
#Override
public boolean onNavigationItemSelected(MenuItem item) {
if(item.isChecked())
item.setChecked(false);
drawerLayout.closeDrawers();
switch (item.getItemId()){
// this is for user
case R.id.test:
Toast.makeText(getApplicationContext(), "Test Selected", Toast.LENGTH_SHORT).show();
TestFragment testFragment = new TestFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameholder, testFragment);
fragmentTransaction.commit();
return true;
// this is for user
case R.id.practice:
Toast.makeText(getApplicationContext(),"Practice Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.existing_questions:
Toast.makeText(getApplicationContext(),"Questions Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.new_questions:
Toast.makeText(getApplicationContext(),"New questions Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.settings:
Toast.makeText(getApplicationContext(),"Settings Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.users_data:
Toast.makeText(getApplicationContext(),"User data Selected",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
Edit:
Here you have the two menus I use:
admin_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/existing_questions"
android:checked="false"
android:icon="#drawable/ic_existq"
android:title="Questions" />
<item
android:id="#+id/new_questions"
android:checked="false"
android:icon="#drawable/ic_addq"
android:title="Add question" />
<item
android:id="#+id/settings"
android:checked="false"
android:icon="#drawable/ic_settings"
android:title="Settings" />
<item
android:id="#+id/users_data"
android:checked="false"
android:icon="#drawable/ic_statistics"
android:title="Statistics" />
</group>
</menu>
user_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/test"
android:checked="false"
android:icon="#drawable/ic_test"
android:title="Test" />
<item
android:id="#+id/practice"
android:checked="false"
android:icon="#drawable/ic_practice"
android:title="Practice" />
</group>
</menu>
A good approach would be to use two groups with different IDs in the same menu. Then you can switch between them easly with .setGroupVisible() like this:
if(name.equals("admin")){
navigationView.menu.setGroupVisible(R.id.menu_group_admin, true);
navigationView.menu.setGroupVisible(R.id.menu_group_user, false);
}
else{
navigationView.menu.setGroupVisible(R.id.menu_group_admin, false);
navigationView.menu.setGroupVisible(R.id.menu_group_user, true);
}
This works seamlessly
Thanks cylon. The mistake was made by me. I inflated the navigation view in the xml, and then from code to.

Categories

Resources