How to generate Navigation Drawer item's dynamically from xml? - android

I prepared 2 xml menu files and placed inside my res/menu folder.
menu_beforeLogin.xml will be displayed if the user didn't logged in.
After they logged in, the menu item will changed to menu_afterLogin.xml.
I tried to called InflateMenu() in my onResume() method, but it ends up with keep adding the items from xml file whenever onResume() is invoked instead of removing/regenerate the menu list.
I would prefer to check user is logged in or not in onResume() method.
What is the proper way to change Navigation Drawer's list dynamically
?
MainActivity.cs
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
...
mDrawer = FindViewById<NavigationView>(Resource.Id.navigation_drawer);
...
}
protected override void OnResume ()
{
base.OnResume ();
string token = pref.GetString (Constant.PREF_TOKEN, "");
mDrawer.InflateMenu ( (token == "") ? Resource.Menu.menu_drawer_notLoggedIn : Resource.Menu.menu_drawer);
mDrawer.Invalidate ();
...
}
layout/main.axml
<android.support.v4.widget.DrawerLayout>
<android.support.design.widget.CoordinatorLayout>
...
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#drawable/menu_background"
app:headerLayout="#layout/drawer_header" />
</android.support.v4.widget.DrawerLayout>
res/menu/menu_beforeLogin.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_login"
android:icon="#drawable/navigation_login"
android:title="#string/navigation_login" />
<item
android:id="#+id/navigation_notice"
android:icon="#drawable/navigation_notice"
android:title="#string/navigation_notice" />
<item
android:id="#+id/navigation_contactUs"
android:icon="#drawable/navigation_contactUs"
android:title="#string/navigation_contactUs" />
</menu>
res/menu/menu_afterLogin.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_notice"
android:icon="#drawable/navigation_notice"
android:title="#string/navigation_notice" />
<item
android:id="#+id/navigation_profile"
android:icon="#drawable/navigation_profile"
android:title="#string/navigation_profile" />
<item
android:id="#+id/navigation_contactUs"
android:icon="#drawable/navigation_contactUs"
android:title="#string/navigation_contactUs" />
<item
android:id="#+id/navigation_logout"
android:icon="#drawable/navigation_logout"
android:title="#string/navigation_logout" />
</menu>

Add this method to clear your menu item before inflating new menu.
mDrawer.Menu.Clear ();

Related

Android: Menu item in left side

Now I have this
But I want to make this:
<?xml version="1.0" encoding="utf-8"?>
<item
android:id="#+id/menu"
android:icon="#drawable/ic_menu"
android:title="#string/title_menu"
app:showAsAction="always" />
<item
android:id="#+id/file"
android:icon="#drawable/ic_file"
android:title="#string/title_file"
app:showAsAction="always" />
<item
android:id="#+id/new_file"
android:icon="#drawable/ic_new_file"
android:title="#string/title_new_file"
app:showAsAction="always" />
<item
android:id="#+id/visual"
android:icon="#drawable/ic_eye"
android:title="#string/title_eye"
app:showAsAction="always" />
<item
android:id="#+id/print"
android:icon="#drawable/ic_print"
android:title="#string/title_print"
app:showAsAction="always" />
<item android:id="#+id/help"
android:icon="#drawable/ic_help"
android:title="#string/title_help" />
This menu I add in activity
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.designer_options_menu, menu)
return true
}
And I don't understand how I can install ic_menu at the left side
You can use the Up/Home button for doing that by using a custom toolbar within a CoordinatorLayout:
1. Main layout
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<!-- My Layout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
2. Your menu
<?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/folder"
android:icon="#drawable/ic_folder_black_24dp"
android:orderInCategory="1"
android:title=""
app:showAsAction="always" />
<item
android:id="#+id/file"
android:icon="#drawable/ic_insert_drive_file_black_24dp"
android:orderInCategory="2"
android:title=""
app:showAsAction="always" />
<item
android:id="#+id/eye"
android:icon="#drawable/ic_remove_red_eye_black_24dp"
android:orderInCategory="3"
android:title=""
app:showAsAction="always" />
<item
android:id="#+id/print"
android:icon="#drawable/ic_print_black_24dp"
android:orderInCategory="4"
android:title=""
app:showAsAction="always" />
</menu>
3. Java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_black_24dp);
getSupportActionBar().setTitle("");
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Toast.makeText(this, "Home", Toast.LENGTH_SHORT).show();
break;
case R.id.eye:
Toast.makeText(this, "Eye", Toast.LENGTH_SHORT).show();
break;
case R.id.file:
Toast.makeText(this, "File", Toast.LENGTH_SHORT).show();
break;
case R.id.folder:
Toast.makeText(this, "Folder", Toast.LENGTH_SHORT).show();
break;
case R.id.print:
Toast.makeText(this, "Print", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
}
4. Style: use NoActionBar theme
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
</resources>
5. Gradle:: add design support library for coordinator layout
implementation 'com.android.support:design:28.0.0'
The result
Simpler Version
Add android:icon to your Main Activity or whatever Activity you want this icon:
<activity
android:name=".Main"
android:icon="#drawable/ic_settings_white_24dp"
android:launchMode="singleTop">
Enable the "home" icon in your Main.java:
getActionBar().setDisplayShowHomeEnabled( true ); // In your onCreate() or wherever.
You might also want to hide the back icon in the top left and the app name in the top left. You can do that with these two commands:
// Disable back icon in top left and hide app name.
getActionBar().setDisplayHomeAsUpEnabled( false );
getActionBar().setDisplayShowTitleEnabled( false );
To handle the click event you just need to capture the home in onOptionsItemSelected:
#Override
public boolean onOptionsItemSelected( MenuItem item ) {
switch( item.getItemId() ) {
case android.R.id.home:
// Do something.
return true;
}
}
Worked for us and the end result is something like this:
With AppCompatActivity
You need to do this slightly differently if your Activity is extending from AppCompatActivity. Here are the changes to the steps above:
No need to add android:icon to AndroidManifest.xml.
Set the Icon to use in your Main.java Activity and use getSupportActionBar():
getSupportActionBar().setHomeAsUpIndicator( R.drawable.ic_settings_white_24dp );

DropDown menu in Nav Bar android

I am busy trying to create a dropdown menu from the default navigation bar option that i used in android studio. I have read many places that you need to use expandable List view but i am not sure how to implement it because i am use to coding. So here is my menudrawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_add"
android:icon="#drawable/ic_playlist_add_black_24dp"
android:title="Add Products" />
<item
android:id="#+id/nav_up"
android:icon="#drawable/ic_create_black_24dp"
android:title="Update or delete Products" />
<item
android:id="#+id/nav_cus"
android:icon="#drawable/ic_local_library_black_24dp"
android:title="Customers" />
<item android:id="#+id/calc"
android:icon="#drawable/baseline_tablet_black_18dp"
android:title="Calculator"/>
--This part under the title Calculator i want a drop down which has different calculator options
</group>
<item android:title="Other Functions">
<menu>
<item
android:id="#+id/nav_send"
android:icon="#drawable/ic_menu_send"
android:title="Logout" />
</menu>
</item>
</menu>
And here is my main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#drawable/background"
tools:openDrawer="start">
<include
layout="#layout/app_bar_emily"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_emily"
app:menu="#menu/activity_emily_drawer" />
</android.support.v4.widget.DrawerLayout>
and here is my .java file:
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_add) {
Intent i = new Intent(this,Products.class);
startActivity(i);
// Handle the camera action
} else if (id == R.id.nav_send) {
Intent jj = new Intent(this,login.class);
startActivity(jj);
}
else if (id == R.id.nav_up) {
Intent jj = new Intent(this,updelProducts.class);
startActivity(jj);
}
else if (id == R.id.nav_cus) {
Intent z = new Intent(this,Customer.class);
startActivity(z);
}
else if (id == R.id.calc) {
Intent jj = new Intent(this, Calc_140_plain.class);
startActivity(jj);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Now i would like to add a drop down menu under the calculator tab where i have different calculators that the takes the user to an appropriate page
If I understood you correctly, you want to show different items inside your menu item. You can do this easily by using <menu> inside the <item>.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="#+id/firstOne"
android:orderInCategory="1"
android:title="First One"
app:showAsAction="ifRoom">
<menu>
<item
android:id="#+id/menuSortNewest"
android:title="1-1" />
<item
android:id="#+id/menuSortRating"
android:title="1-2" />
</menu>
</item>
<item
android:id="#+id/action_refresh"
android:orderInCategory="2"
android:title="Second One"
app:showAsAction="ifRoom"/>
</menu>
For example, the code above will show two different items called First One and Second One. When you click the First One, you will see two different options called 1-1 and 1-2. I hope, this helps.
Have a beautiful day!

Event click a item on android.support.design.widget.NavigationView

I'm new student on xamarin android. so I don't know how to create a event click on that.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_home_black_48dp"
android:title="Home" />
<item
android:id="#+id/nav_genre"
android:icon="#drawable/ic_toc_black_48dp"
android:title="Genres" />
<item
android:id="#+id/nav_audio"
android:icon="#drawable/ic_settings_input_antenna_black_48dp"
android:title="Audio" />
<item
android:id="#+id/nav_download"
android:icon="#drawable/ic_get_app_black_48dp"
android:title="Download" />
</group>
<item android:title="Account">
<menu>
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_about"
android:icon="#drawable/ic_lock_open_black_48dp"
android:title="About"/>
<item
android:id="#+id/nav_signout"
android:icon="#drawable/ic_perm_identity_black_48dp"
android:title="Sign out"/>
</group>
</menu>
</item>
</menu>
<!-- your content layout -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:titleTextColor="#android:color/background_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<frameLayout
android:id:="#+id/frameContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
</LinearLayout>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:id="#+id/nav_view"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/navmenu" />
</android.support.v4.widget.DrawerLayout>
I want to when click that item 1 -> fragmenthome(there only listview)
I want to when click that item 2 -> fragmentgenres(there only listview)
They all be showing up in frameContainer.
This is how to handle click events and load fragments accordingly.
HomeFragment homFragment;
GenresFragment genresFragment;
int currentFragmentId=Resource.Id.nav_home;
Above declarations are to be made global in the Activity.
var navigationView = FindViewById<NavigationView> (Resource.Id.nav_view);
navigationView.NavigationItemSelected+= NavigationView_NavigationItemSelected;
CreateFragments ();
LoadInditialFragment ();
Add the above snippets in OnCreate.
void CreateFragments()
{
homeFragment = new HomeFragment ();
genresFragment = new GenresFragment ();
}
void LoadInditialFragment()
{
var transaction = FragmentManager.BeginTransaction ();
transaction.Add (Resource.Id.frameContainer, genresFragment).Hide(genresFragment);
transaction.Add (Resource.Id.frameContainer, homeFragment);
transaction.Commit ();
}
void NavigationView_NavigationItemSelected (object sender, NavigationView.NavigationItemSelectedEventArgs e)
{
if (e.MenuItem.ItemId != currentFragmentId)
SwitchFragment (e.MenuItem.ItemId);
drawerLayout.CloseDrawers ();
}
void SwitchFragment(int FragmentId)
{
var transaction = FragmentManager.BeginTransaction ();
switch (currentFragmentId)
{
case Resource.Id.nav_home:
transaction.Hide (homeFragment).Commit ();
break;
case Resource.Id.nav_genre:
transaction.Hide (genresFragment).Commit ();
break;
}
transaction = FragmentManager.BeginTransaction ();
switch (FragmentId)
{
case Resource.Id.nav_home:
transaction.Show (homeFragment);
transaction.Commit ();
break;
case Resource.Id.nav_genre:
transaction.Show (genresFragment);
transaction.Commit ();
break;
}
currentFragmentId = FragmentId;
}
In the Create Fragment Method All Fragments are instantiated initially and attached to the Fragment. Then all fragments except the fragment to be shown are hidden. Then as the user clicks on an item in NavigationView the current fragment is hidden and the fragment corresponding to the menu item is shown. In this approach each fragment will not be created each time user switches menu. Thus pages will load faster.

Change the color of a checked menu item in a navigation drawer

I am using the new Android Design Support library to implement a navigation drawer in my application.
I can't figure out how to change the color of a selected item!
Here is the xml of the menu :
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/navigation_item_1"
android:icon="#drawable/ic_1"
android:title="#string/navigation_item_1"/>
<item
android:id="#+id/navigation_item_2"
android:icon="#drawable/ic_2"
android:title="#string/navigation_item_2"/>
</group>
And here is the navigationview xml which is placed inside a android.support.v4.widget.DrawerLayout :
<android.support.design.widget.NavigationView
android:id="#+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/drawer_header"
app:itemIconTint="#color/black"
app:itemTextColor="#color/primary_text"
app:menu="#menu/menu_drawer">
<TextView
android:id="#+id/main_activity_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:textColor="#color/primary_text" />
</android.support.design.widget.NavigationView>
Thank you for your help !
[EDIT]
I have already looked at solutions such as this one : Change background color of android menu.
It seems to be quite a hack and I thought that with the new Design Support Library, something cleaner would have been introduced?
Well you can achieve this using Color State Resource. If you notice inside your NavigationView you're using
app:itemIconTint="#color/black"
app:itemTextColor="#color/primary_text"
Here instead of using #color/black or #color/primary_test, use a Color State List Resource. For that, first create a new xml (e.g drawer_item.xml) inside color directory (which should be inside res directory.) If you don't have a directory named color already, create one.
Now inside drawer_item.xml do something like this
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="checked state color" android:state_checked="true" />
<item android:color="your default color" />
</selector>
Final step would be to change your NavigationView
<android.support.design.widget.NavigationView
android:id="#+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/drawer_header"
app:itemIconTint="#color/drawer_item" // notice here
app:itemTextColor="#color/drawer_item" // and here
app:itemBackground="#android:color/transparent"// and here for setting the background color to tranparent
app:menu="#menu/menu_drawer">
Like this you can use separate Color State List Resources for IconTint, ItemTextColor, ItemBackground.
Now when you set an item as checked (either in xml or programmatically), the particular item will have different color than the unchecked ones.
I believe app:itemBackground expects a drawable. So follow the steps below :
Make a drawable file highlight_color.xml with following contents :
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="YOUR HIGHLIGHT COLOR"/>
</shape>
Make another drawable file nav_item_drawable.xml with following contents:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/highlight_color" android:state_checked="true"/>
</selector>
Finally add app:itemBackground tag in the NavView :
<android.support.design.widget.NavigationView
android:id="#+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/drawer_header"
app:itemIconTint="#color/black"
app:itemTextColor="#color/primary_text"
app:itemBackground="#drawable/nav_item_drawable"
app:menu="#menu/menu_drawer">
here the highlight_color.xml file defines a solid color drawable for the background. Later this color drawable is assigned to nav_item_drawable.xml selector.
This worked for me. Hopefully this will help.
********************************************** UPDATED **********************************************
Though the above mentioned answer gives you fine control over some properties, but the way I am about to describe feels more SOLID and is a bit COOLER.
So what you can do is, you can define a ThemeOverlay in the styles.xml for the NavigationView like this :
<style name="ThemeOverlay.AppCompat.navTheme">
<!-- Color of text and icon when SELECTED -->
<item name="colorPrimary">#color/color_of_your_choice</item>
<!-- Background color when SELECTED -->
<item name="colorControlHighlight">#color/color_of_your_choice</item>
</style>
now apply this ThemeOverlay to app:theme attribute of NavigationView, like this:
<android.support.design.widget.NavigationView
android:id="#+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:theme="#style/ThemeOverlay.AppCompat.navTheme"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/menu_drawer">
I hope this will help.
One need to set NavigateItem checked true whenever item in NavigateView is clicked
//listen for navigation events
NavigationView navigationView = (NavigationView)findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
// select the correct nav menu item
navigationView.getMenu().findItem(mNavItemId).setChecked(true);
Add NavigationItemSelectedListener on NavigationView
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
// update highlighted item in the navigation menu
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());
}
}, DRAWER_CLOSE_DELAY_MS);
return true;
}
Step 1: Build a checked/unchecked selector:
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/yellow" android:state_checked="true" />
<item android:color="#color/white" android:state_checked="false" />
</selector>
Step 2: use the XML attribute app:itemTextColor within NavigationView widget for selecting the text color.
<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 & 4:
Step 3: To make menu icons check-able: wrap all items in a <group> and setandroid:checkableBehavior="single"
Step 4: To change icon color: set the selector to all the items with app:iconTint
<?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">
<group android:checkableBehavior="single">
<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" />
</group>
</menu>
Step 5:: make sure that onNavigationItemSelected() callback returns true to consume selection event
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
Result:
Side Note:
If setting android:checkableBehavior="single" not working, then you handle this programmatically by manually making the selected item checked and clear the previously selected item:
#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:
...
}
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);
}
}
Here is the another way to achive this:
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
item.setEnabled(true);
item.setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
return false;
}
});
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Here's how you can do it in your Activity's onCreate method:
NavigationView navigationView = findViewById(R.id.nav_view);
ColorStateList csl = new ColorStateList(
new int[][] {
new int[] {-android.R.attr.state_checked}, // unchecked
new int[] { android.R.attr.state_checked} // checked
},
new int[] {
Color.BLACK,
Color.RED
}
);
navigationView.setItemTextColor(csl);
navigationView.setItemIconTintList(csl);
if you want to keep the fillet of selected item in material 3, use app:itemShapeFillColor="#color/main_navigation_view" instead of app:itemBackground="#color/main_navigation_view"

Ripple effect using itemBackground on NavigationView

I wonder if anyone is having problems when redefining the background of the items on a NavigationView with app:itemBackground"? I get the behavior shown on the screenshot, no matter what item I press the last item shows the ripple instead.
Here is my drawer_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single" android:id="#+id/first_group">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_home"
android:title="#string/nav_home" />
</group>
<group android:id="#+id/second_group">
<item
android:id="#+id/nav_settings"
android:title="#string/nav_settings" />
<item
android:id="#+id/nav_about"
android:title="#string/nav_about" />
<item
android:id="#+id/nav_logout"
android:title="#string/nav_logout" />
</group>
</menu>
My my_ripple.xml:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#ffff0000">
<item
android:id="#android:id/mask"
android:drawable="#android:color/white" />
</ripple>
My NavigationView:
<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="#android:color/white"
app:headerLayout="#layout/drawer_header"
app:itemBackground="#drawable/my_ripple"
app:itemIconTint="#color/drawer_item"
app:itemTextColor="#color/drawer_item"
app:menu="#menu/drawer_menu" />
Possible workaround for now - Just for people looking and just in case....
Adding addOnGlobalLayoutListener in onCreate for the navigation view and applying the Drawable on each menu item.
/**
* Contains the {#link MenuItem} views in the {#link NavigationView}
*/
private final ArrayList<View> mMenuItems = new ArrayList<>(5);
// Grab the NavigationView Menu
final Menu navMenu = mNavigationView.getMenu();
mNavigationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Remember to remove the installed OnGlobalLayoutListener
mNavigationView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Loop through and find each MenuItem View
for (int i = 0, length = 5; i < length; i++) {
final MenuItem item = navMenu.getItem(i);
mNavigationView.findViewsWithText(mMenuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT);
}
// Loop through each MenuItem View and apply your custom Typeface
for (final View menuItem : mMenuItems) {
//Create RippleDrawable called myRipple
((TextView) menuItem).setBackground(myRipple);
}
}
});
Ripple drawables should be defined like this sample:
<!-- A red ripple masked against an opaque rectangle. -->
<ripple android:color="#ffff0000">
<item android:id="#android:id/mask"
android:drawable="#android:color/white" />
</ripple>
read more
https://developer.android.com/reference/android/graphics/drawable/RippleDrawable.html
Apply the itemBackground attribute to the menu rather than the NavigationView. The ripple will then stay contained to the menu item handling the touch event.

Categories

Resources