Bottom Navigation view icon change not working - android

I want to change to icons of the bottom navigation view as we switch items.
I have light blue icons and dark blue icons for selected items.
I am using selector drawable for each navigation item but I see the images like below in grey as inactive and blue as active
Here is my code
bottom_nav_menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/home_icon_selector"
android:title="#string/title_home" />
<item
android:id="#+id/navigation_scheduler"
android:icon="#drawable/schelduler_icon_selector"
android:title="#string/title_scheduler" />
<item
android:id="#+id/navigation_favourites"
android:icon="#drawable/favourites_icon_selector"
android:title="#string/title_favourites" />
<item
android:id="#+id/navigation_settings"
android:icon="#drawable/settings_icon_selector"
android:title="#string/title_settings" />
</menu>
home
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_20"
android:layout_marginLeft="#dimen/margin_20"
android:layout_marginRight="#dimen/margin_20"
android:layout_marginEnd="#dimen/margin_20"
android:layout_marginBottom="#dimen/margin_8"
android:background="#drawable/bottom_navigation_background"
android:elevation="8dp"
app:itemIconTint="#drawable/bottom_navigation_color_selector"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
And selectors
scheduler selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_scheduler_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_scheduler_blue" android:state_checked="true"/>
</selector>
Settings selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_settings_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_settings_blue" android:state_checked="true"/>
</selector>
Favorites selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_favorites_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_favourites_blue" android:state_checked="true"/>
</selector>
Home Selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/qa_home_inactive" android:state_checked="false"/>
<item android:drawable="#drawable/ic_home" android:state_checked="true"/>
</selector>
Activity code
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_scheduler, R.id.navigation_favourites, R.id.navigation_settings))
// setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
What am I doing wrong here? Please help...
Edit :
I am using following drawables
enter link description here
enter link description here

The reason of this issue is that there is always a value for app:itemIconTint, even if it is not used, it takes the default values of the primary/accent colors.
So to solve your problem you need to explicitly disable this with:
val btmNav = findViewById<BottomNavigationView>(R.id.nav_view)
navView.itemIconTintList = null
Although I do recommend another thing:
The icons are already the same icons in checked/unchecked states, but with different tint colors. If these icons are vectors, then you can just tint colors using a selector in app:itemIconTint, and use a single version of the icon without needing to duplicate the resources:
icon_color_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#2596CD" android:state_checked="true" />
<item android:color="#84D0F4" android:state_checked="false" />
</selector>
And apply that:
<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:itemIconTint="#drawable/icon_color_selector"
And keep the menu items only with icons not the selectors, for instance:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_home"
android:icon="#drawable/home_icon" //<<<<< icon not selector
android:title="#string/title_home" />
....
</menu>
UPDATE:
As you are using navigation architecture components, make sure to have the same ids in the bottomNavView menu that matches the corresponding ones in the navGraph of the bottomNavView fragments.
In case you don't use a navGraph for the bottomNavView fragments, then you can't use navView.setupWithNavController(navController)
Here is with your drawable icon

This is just a wild guess, but maybe this line here:
app:itemIconTint="#drawable/bottom_navigation_color_selector"
is interfering with the colors of your drawables? If your drawables have the right colors (light blue/dark blue) they should work with your current selectors.
Alternatively, check that you don't set app:itemIconTint for the bottom-nav some other way, eg through a theme or programmatically!

You can achieve this using using selector like #Chris said or you can do it dynamically by using setOnNavigationItemSelectedListener{}
update - For changing icons , you can just brute force by changing the current item.icon to filled and others to unfilled icon , see here to get a gist of it (don't copy its for tabLayout).
navView.setOnNavigationItemSelectedListener { item ->
// change the icon to filled icon
true
}
It seems so that listner is depreciated so refer this

Related

BottomNavigationView - Android Studio

I have used images as icon but I dont want them to look grey when they are not selected. It should look same as picture whether its active or not. What should I do?
com.google.android.material.bottomnavigation.BottomNavigationView
Thanks
Try using this in your XML file in the BottomNavigationView part
app:itemIconTint="null"
Or add this to your java file after defining your BottomNavigationView (with the findViewById)
//Replace BottomNavView with your nav bar id
BottomNavView.setItemIconTintList(null);
A long way to achieve it
mBottomNav.setItemIconTintList(null);
Then do the designs yourself. Don't forget to separate the buttons as clicked and not clicked.
Example Button XML
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--Clicked-->
<item android:drawable="#drawable/homeclicked" android:state_checked="true" />
<!--Not Clicked-->
<item android:drawable="#drawable/homenotclicked" android:state_checked="false" />
</selector>
And add them to the view: Example bottom_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/homebuttons"
android:icon="#drawable/homebuttonxml />
<!--Other Buttons...-->
</menu>
And finally, Link view to bottomnavigationview
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:labelVisibilityMode="unlabeled"
app:elevation="0dp"
app:menu="#menu/bottom_navigation">
</com.google.android.material.bottomnavigation.BottomNavigationView>
The default color used by not selected items is based on the colorOnSurface color.
Just use:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:theme="#style/BottomNavigationViewThemeOverlay"
.... />
with:
<style name="BottomNavigationViewThemeOverlay">
<item name="colorOnSurface">#color/...</item>
</style>
Otherwise you can define your custom selector:
<com.google.android.material.bottomnavigation.BottomNavigationView
app:itemIconTint="#color/bottomnavicontint"
../>
with:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="1.0" android:color="?attr/colorPrimary" android:state_checked="true"/>
<item android:alpha="0.6" android:color="#color/..."/>. <!-- not selected -->
</selector>

Custom icons - Bottom Navigation View

I have a BottomNavigationView and want to have custom icons for both selected and unselected state.Tried using selector but its not working.
Any idea how to place custom icons ?
Edit - Adding code from comments into the Question
<item
android:id="#+id/navigation_card"
android:icon="#drawable/iv_home_card"
app:itemBackground="#drawable/navigation_card"
app:showAsAction="ifRoom" tools:ignore="MenuTitle"
/>
Like this I have added the icon. Now for selected state, it stroke it with theme color but I want to replace the icon with another icon.
I tried making selector but did not work
<selector
xmlns:android="schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="#drawable/btn_star_off_normal" />
<item android:state_checked="true"
android:drawable="#drawable/btn_star_on_normal" />
</selector>
BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) { }
return false;
}
};
You can simply create drawable selector in drawable folder and image can be change according to the state of the widget used in view
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/home_active" android:state_checked="true"/>
<item android:drawable="#drawable/home_inactive" android:state_checked="false"/>
and set this selector in bottom nav menu file
<item
android:id="#+id/navigation_home"
android:icon="#drawable/nav_home_selector"
android:title="#string/tab_home_title" />
Make sure to add this line to your java file. This solution will not work for selected icon unless you add this line.
bottomNavigationView.setItemIconTintList(null);
This will disable tint effect of selected item icon.
BottomNavigationView will get its icons from the menu file so you cannot set them from your selector drawable. However, if you want to change their color for selected and not selected states you can do this as below.
Create your selector drawable nav_item_color_state as below
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/white" android:state_enabled="true" />
<item android:color="#color/colorPrimary" android:state_enabled="false" />
</selector>
set itemIconTint and itemTextColor using selector drawable as below and it will change color of your icon and text when selected.
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:itemIconTint="#drawable/nav_item_color_state"
app:itemTextColor="#drawable/nav_item_color_state"
app:menu="#menu/bottom_navigation_main" />
Check documentation from here
for some reason, "state_enabled" wasn't working in my case so I used the below-given selector.
nav_color_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/black" android:state_checked="true" />
<item android:color="#color/grey" android:state_checked="false" />
</selector>
Along with BottomNavigationView as
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
app:itemIconTint="#drawable/nav_color_selector"
app:itemTextColor="#drawable/nav_color_selector"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
This code changed the filled color of vector drawables which I linked in the bottom_nav_menu.xml

How to change selected icon image in BottomNavigationView in android?

I have inflated menu_main.xml to BottomNavigationView and now i want to change the icons in BottomNavigation when we select an item .
If above solution is not working for you to change selected item icon then add below line to your code:
bottomNavigationView.setItemIconTintList(null);
This will disable color tint effect of selected item icon and change the icon as per your selector drawable.
I had the same problem. I have added selector drawable for changing icon of BottomNavigationView item when its checked/selected.
Create item called selector in drawable folder and icon can be changed according to the selected state of the widget used
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/icon_green" android:state_checked="true"/>
<item android:drawable="#drawable/icon_black" android:state_checked="false"/>
</selector>
Use selector as a menu icon in navigation
You have to save this in the res/drawable directory.
And use it as follows:
ex: bottomNavigationMenu.xml
...
android:icon="#drawable/your_selector"
Xml of Bottom NavigationView
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemIconTint="#drawable/selector_bottom_navigation"
app:itemTextColor="#drawable/selector_bottom_navigation"
app:menu="#menu/bottom_navigation" />
Bottm Navigation 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/action_home"
android:icon="#drawable/selecter_tab_home"
android:title="#string/text_home"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_explore"
android:icon="#drawable/selector_tab_explore"
android:title="#string/text_explore"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_profile"
android:icon="#drawable/selector_tab_profile"
android:title="#string/text_profile"
app:showAsAction="ifRoom" />
</menu>
Selector of home menu you can put next two same also with differnt drawable file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_tab_home" android:state_checked="false"/>
<item android:drawable="#drawable/ic_tab_home_fill" android:state_checked="true"/>
</selector>

Is there a way to have different icon/color for selected state of Android's BottomNavigationView?

The following is the XML for my current BottomNavigationView. Currently, all three of the icon drawables are unfilled icons with the same color. I would like be able to present a filled in version of the icon when that state is selected as well as possibly changing the color to make it obvious it is the current icon state. The following image is an example of what I mean.
<?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/action_favorites"
android:enabled="true"
android:icon="#drawable/icon_flyer"
android:title="Flyer"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_schedules"
android:enabled="true"
android:icon="#drawable/icon_list"
android:title="List"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_music"
android:enabled="true"
android:icon="#drawable/icon_contact"
android:title="Contact"
app:showAsAction="ifRoom" />
</menu>
To change the icon color by state you can set a color state drawable for the "itemIconTint" property in your BottomNavigationView. For the text color you can set the same color state drawable in the "itemTextColor" property. Here is an example of a color state drawable for the BottomNavigationView:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/green" android:state_pressed="true" />
<item android:color="#color/green" android:state_checked="true" />
<item android:color="#color/gray" />
</selector>
The "android:state_pressed" state is the menu item's pressed state. The "android:state_checked" is the menu item's selected state.
This only changes the color of the icons and labels in your BottomNavigationView. For filling your icon you can set an icon state drawable for the "icon" property in your menu item. Here is an example of an icon state drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_favorites_filled" android:state_checked="true" />
<item android:drawable="#drawable/ic_favorites" />
</selector>
Create res/color/bottom_nav_color.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="your_highlight_color" />
<item android:state_pressed="true" android:color="your_highlight_color" />
<item android:color="your_inactive_color" />
</selector>
Then in your BottomNavigationView:
app:itemTextColor="#color/bottom_nav_color"
app:itemIconTint="#color/bottom_nav_color"
Step 1: add all the icons to your drawable folders
Step 2: create new drawable resource file for each icon. In the file named "bottom_navigation_icon" (for example), specify selectors. The default icon needs to be stated in the last line:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_home_active"
android:state_checked="true"/>
<item android:drawable="#drawable/ic_home_inactive"/>
</selector>
Step 3: in your menu for the bottom navigation, set the code below for each item:
android:icon="#drawable/bottom_navigation_icon"
That's all. Now your icon changes when you click on it and changes back to the previous one when you click away!
You can set a StateDrawable to your menuitem.
Create an xml file in your drawable folder with the following code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_pressed_green"
android:state_pressed="true" />
<item android:drawable="#drawable/button_normal" />
</selector>
Update the xml file that it fits your needs (state and drawable) and reference it in your menuitem instead of your current icon.

Navigation View's selectors behave incorrectly

I'm following this color scheme of Navigation View.
I created 3 selectors, for background, text and icon.
When I set the selectors, my navigation view looked like this:
The problem is that no item is shown selected and if I press one item, all items' background color changes to gray. Icon never gets the primary color.
Here is are the XMLs:
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:itemTextColor="#drawable/nav_item_text"
app:itemIconTint="#drawable/nav_item_icon_tint"
app:itemBackground="#drawable/nav_item_background"
app:headerLayout="#layout/drawer_student_data_header"
app:menu="#menu/drawer"
android:id="#+id/navigationView"/>
nav_item_icon_tint.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/gray_600"/>
<item android:state_selected="true" android:color="#color/primary" />
<item android:color="#color/gray_600" />
</selector>
nav_item_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/black_87_percent"/>
<item android:state_selected="true" android:color="#color/primary" />
<item android:color="#color/black_87_percent" />
</selector>
nav_item_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#color/gray_400"/>
<item android:state_selected="true" android:drawable="#color/gray_200" />
<item android:drawable="#android:color/white" />
</selector>
I've had a similar problem and looks like the way to solve it is to use android:state_checked instead of the android:state_selected in all three selectors (at least that solved it for me).
You can use setItemTextColor and setItemIconTintList for set text color tint and icon color tint to item of NavigationDrawer,
To use this methods add this code to end of onCreateView:
int[][] states = new int[][]{
new int[]{-android.R.attr.state_checked},// unchecked state
new int[]{android.R.attr.state_checked}, // checked state
};
int[] colors = new int[]{
ContextCompat.getColor(this, R.color.colorPrimary),
ContextCompat.getColor(this, R.color.colorPrimaryDark)
};
ColorStateList colorStateList = new ColorStateList(states, colors);
navigationView.setItemTextColor(colorStateList);
navigationView.setItemIconTintList(colorStateList);
This code set color to unchecked state and checked state. You can set color to other states.
Color array and state array should be have equals member count. You can select color whatever you want.
You can use Color class or like the sample use resource. In this link you can find list of available states developer.android.
Make sure you are not accessing the menu item from bottom navigation and setting its state to 'checked' twice. To avoid that, use:
mBottomNavigationView.selectedItemId(R.id.your_menu_item_id);
instead of
mBottomNavigationView.menu.getItem(position).setChecked(true);

Categories

Resources