I have added BottomNavigationView in my application like.
main.xml
<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:itemBackground="#color/colorPrimary"
app:itemIconTint="#color/white"
app:itemTextColor="#color/white"
app:menu="#menu/bottom_navigation_main" />
bottom_navigation_main.xml
<?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/ic_favorite_white_24dp"
android:title="#string/text_favorites"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_schedules"
android:enabled="true"
android:icon="#drawable/ic_access_time_white_24dp"
android:title="#string/text_schedules"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_music"
android:enabled="true"
android:icon="#drawable/ic_audiotrack_white_24dp"
android:title="#string/text_music"
app:showAsAction="ifRoom" />
</menu>
MainActivity click
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_favorites:
//need change icon of favotites here.
case R.id.action_schedules:
case R.id.action_music:
}
return true;
}
});
I want to change the icon of the bottom navigation of selected position. How can we achieve this feature when user click one item?
(if user clicked one item then the icon change to another one)
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/calender_green" android:state_checked="true"/>
<item android:drawable="#drawable/calender_black" android:state_checked="false"/>
</selector>
I found this is better approach to use selector drawable:
At first create an xml file in your drawable folder.
For example, xml file name is child_selector.xml at drawable folder.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/child" android:state_checked="false"/>
<item android:drawable="#drawable/child_fill" android:state_checked="true"/>
</selector>
Simply add child_selector in menu item of your bottom_navigation_main.xml:
Like: android:icon="#drawable/child_selector"
Example:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_child"
android:icon="#drawable/child_selector"
android:title="#string/title_child" />
</menu>
And must add following line in your activity-
bottomNavigationView.setItemIconTintList(null);
If above solutions are not working for you to change selected item icon then add below line to your code:
bottomNavigationView.setItemIconTintList(null);
This will disable tint effect of selected item icon.
I had the same problem. I have added selector drawable for changing icon of BottomNavigationView item when its checked/selected.
You need to reset the icon onclick, and then on the switch case you need to set only the one you need to change, so only when selected the icon change.
Menu menu = bottomNavigationView.getMenu();
menu.findItem(R.id.action_favorites).setIcon(favDrawable);
switch (item.getItemId()) {
case R.id.action_favorites:
item.setIcon(favDrawableSelected);
case R.id.action_schedules:
case R.id.action_music:
}
Okay I wanted to understand how to have each item have their own image, and with some confusion in the comments on where it should go, I wanted to type up this answer.
First create your menu and its items. Your selector will go inside those items in the ICON value. Here we have 2 selectors, each made for its menu item.
item
android:id="#+id/navigation_home"
android:icon="#drawable/navigation_home_selector"
android:title="#string/title_home" />
item
android:id="#+id/navigation_profile"
android:icon="#drawable/navigation_profile_selector"
android:title="#string/title_profile" />
Now here is your selector file that will be housed in your drawable folder.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/menu_selected" android:state_checked="true"/>
<item android:drawable="#drawable/menu" android:state_checked="false"/>
</selector>
Final step was provided by #
KishanSolanki124
Add this line of code to your BottomNavigationView.
BottomNavigationView.setItemIconTintList(null);
There you have it. All works like a charm.
The above answer from ajay singh https://stackoverflow.com/a/57248961/9793057 helped me out, as well as employing answers from above.
The following code within res->drawable folder (selector_stock_bottom_nav_view.xml)
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/button_and_tab_color" android:state_checked="true" />
<item android:color="#android:color/darker_gray" android:state_checked="false" />
</selector>
These are the attributes in my bottom navigation view
<com.google.android.material.bottomnavigation.BottomNavigationView
app:itemIconTint="#drawable/selector_stock_bottom_nav_view" //To change icon color
app:itemTextColor="#drawable/selector_stock_bottom_nav_view" //To change text color
app:itemTextAppearanceActive="#style/stockBottomNavigationView.Active" //To change size of text during active state
app:itemTextAppearanceInactive="#style/stockBottomNavigationView.InActive"
app:menu="#menu/bottom_navigation_menu"
app:labelVisibilityMode="labeled"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
app:selectedBackgroundVisible="false"
android:id="#+id/stock_bottom_navigation"/>
I DID-NOT use "BottomNavigationView.setItemIconTintList(null)" anywhere in my code.
Now here comes the most important piece of code, make sure to return "TRUE" in bottom navigation view's listener, i.e,
private BottomNavigationView.OnNavigationItemSelectedListener stockBottomNavListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
return true;
}
};
Bonus: To change size of text active/inactive state
Place the following code in styles.xml file
<style name="stockBottomNavigationView.InActive" parent="#style/TextAppearance.AppCompat.Caption">
<item name="android:textSize">7sp</item>
</style>
<style name="stockBottomNavigationView.Active" parent="#style/TextAppearance.AppCompat.Caption">
<item name="android:textSize">8sp</item>
</style>
The above answer is a compilation of answers from various answers in stackoverflow related to bottom navigation views, icon & text color/size change.
Thanks for the selector method, that works for me (api v26)
For those who wondering how to set it back to origin unselected icon programmatically, consider add this to your OnNavigationItemSelectedListener before your switch(Java) or when(Kotlin) :
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
navigation.menu.getItem(0).setIcon(R.drawable.ic_tab_home)
navigation.menu.getItem(1).setIcon(R.drawable.ic_tab_account)
navigation.menu.getItem(2).setIcon(R.drawable.ic_tab_trading)
navigation.menu.getItem(3).setIcon(R.drawable.ic_tab_wallet)
when (item.itemId) {
R.id.navigation_home -> {
message.setText(R.string.title_home)
item.setIcon(R.drawable.ic_tab_home_active)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_account -> {
message.setText(R.string.title_account)
item.setIcon(R.drawable.ic_tab_account_active)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_trading -> {
message.setText(R.string.title_trading)
item.setIcon(R.drawable.ic_tab_trading_active)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_wallet-> {
message.setText(R.string.title_wallet)
item.setIcon(R.drawable.ic_tab_wallet_active)
return#OnNavigationItemSelectedListener true
}
}
false
}
Found the answer. we can use
item.setIcon(R.drawable.icon_name)
to change the icon .. will try to imporve answer
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_favorites:
//change the icon
item.setIcon(R.drawable.icon_name);
case R.id.action_schedules:
case R.id.action_music:
}
return true;
}
});
You can dynamically set your icon using this method.
R.id.navigation_menu is your item id in your R.menu.menu_bottom_navigation.
val menuItem = bottomNavigationView.menu.findItem(R.id.navigation_menu)
menuItem.setIcon(R.drawable.ic_icon)
On Material 3
You need to create a style and put your colors on:
<style name="BottomNavigationView">
<item name="colorSecondaryContainer">#color/background_dark</item>
<item name="colorSurface">?attr/colorPrimaryVariant</item>
<!-- Icon color Active -->
<item name="colorOnSecondaryContainer">#color/yellow</item>
<!-- Text Color Active -->
<item name="colorOnSurface">#color/yellow</item>
</style>
To see inactive colors, check the documentation.
In the Latest material Design library default behavior of BottomNavigation is provided where you don't need to provide property itemIconTint it will manage it automatically.
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_alignParentBottom="true"
android:background="?android:attr/windowBackground"
app:itemBackground="#color/white"
app:itemTextColor="#color/textBlue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_navigation"
app:labelVisibilityMode="labeled"
app:itemTextAppearanceActive="#color/colorPrimary"
/>
Related
I'm trying to make a bottom navigation a bit tricky.
Indeed I want this kind of bottom navigation :
Each tab has a different color when it is selected. For example measure will be in red when selected (icon and title) and profile will be green when selected...
So I tried to use a selector per item (in my menu)
But the color is not applied. The icon change successfully (I tried to put a completely different icon when an item is selected) but not the color of the title of the tab.
I tried to remove 2 properties from my bottom navigation :
app:itemTextColor="#color/black"
app:itemIconTint="#color/black"
But it's getting worse because the color of my theme app (primary) is applied when a tab is selected.
My bottom nav :
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
app:menu="#menu/main_bottom_navigation"
style="#style/BottomNavigationView"
app:labelVisibilityMode="labeled"
android:layout_alignParentBottom="true" />
One of my selector (logic applied to all items):
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Pressed state -->
<item android:drawable="#drawable/bottom_bar_journal_on"
android:color="#color/red_FF623E"
android:state_checked="true"/>
<!-- Default state -->
<item android:drawable="#drawable/bottom_bar_journal_off"
android:color="#color/background_yellow"
android:state_checkable="false"/>
</selector>
And my menu (where I apply all of my selector) :
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_journal"
android:enabled="true"
android:icon="#drawable/bottom_bar_journal"
android:title="#string/main_menu_journal"
app:showAsAction="withText" />
<item
android:id="#+id/action_measure"
android:enabled="true"
android:icon="#drawable/bottom_bar_measure_off"
android:title="#string/main_menu_measure"
app:showAsAction="withText" />
<item
android:id="#+id/action_add"
android:enabled="false"
android:title=""
app:showAsAction="withText" />
<item
android:id="#+id/action_treatment"
android:enabled="true"
android:icon="#drawable/bottom_bar_treatment_off"
android:title="#string/main_menu_treatment" />
<item
android:id="#+id/action_profile"
android:enabled="true"
android:icon="#drawable/bottom_bar_profile"
android:title="#string/main_menu_profile"
app:showAsAction="withText" />
</menu>
Bottom navigation bar overrides icon colors via app:itemIconTint, but removing that attribute from the XML just makes the nav bar use the app's default colors instead. To prevent the bar from applying color changes, and let your selectors work as intended, you have to set the icon tint list to null in code, like this:
bottom_navigation_bar.itemIconTintList = null
EDIT: I see you want to color the text as well, that's a bit trickier. Only solution I can come up with is to forget about drawable selectors, and just replace the item's icon tint list and text color every time the bottom nav bar selection changes. In your navbar-hosting activity, define these two:
private val bottomNavBarStateList = arrayOf(
intArrayOf(android.R.attr.state_checked),
intArrayOf(-android.R.attr.state_checked)
)
private fun updateBottomNavBarColor(currentSelectedColor: Int) {
val colorList = intArrayOf(
ContextCompat.getColor(this, currentSelectedColor),
ContextCompat.getColor(this, R.color.text_tertiary)
)
val colorStateList = ColorStateList(bottomNavBarStateList, colorList)
bottom_navigation_bar.itemIconTintList = colorStateList
bottom_navigation_bar.itemTextColor = colorStateList
}
Then in your navbar's ItemSelectedListener, call updateBottomNavBarColor with the color you want:
bottom_navigation_bar.setOnNavigationItemSelectedListener {
when(it.itemId) {
R.id.bottom_nav_action_treatment -> {
updateBottomNavBarColor(R.color.treatment)
}
R.id.bottom_nav_action_profile -> {
updateBottomNavBarColor(R.color.profile)
}
else -> {
}
}
}
And you would use it like this on your BottomNavigationView:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
app:itemIconTint="#drawable/bottom_navigation_colors"
app:itemTextColor="#drawable/bottom_navigation_colors"
app:menu="#menu/bottom_navigation_menu" />
The app:itemIconTint and app:itemTextColor take a ColorStateList instead of a simple color. This means that you can write a selector for these colors that responds to the items’ state changes.
For example, you could have a bottom_navigation_colors.xml ColorStateList that contains:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="true"
android:color="#color/colorPrimary" />
<item
android:state_checked="false"
android:color="#color/grey" />
</selector>
used Colored Material Style
style="#style/Widget.MaterialComponents.BottomNavigationView.Colored"
Also Check out this Link : Hands-on with Material Components
Also change colour by programmatically like this:
getMenuInflater().inflate(R.menu.menu_home, menu);
Drawable drawable = menu.findItem(R.id.action_clear).getIcon();
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable, ContextCompat.getColor(this,R.color.textColorPrimary));
menu.findItem(R.id.action_clear).setIcon(drawable);
return true;
Or :
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_favorites:
//need change color of favotites here.
case R.id.action_schedules:
case R.id.action_music:
}
return true;
}
});
I am creating an app in which I created a bottom navigation bar. Now what I want is to set separate colors for selected/unselected state of nav bar items. So I created an xml file and set it for item tint and text color for navigation bar as shown:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#android:color/holo_blue_dark" />
<item android:color="#android:color/darker_gray" />
</selector>
and in main menu adding navigation bar as:
<android.support.design.widget.BottomNavigationView
android:id="#+id/mainNav"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#android:color/white"
android:elevation="8dp"
app:itemIconTint="#color/nav_bar_item_state"
app:itemTextColor="#color/nav_bar_item_state"
app:menu="#menu/nav_items"></android.support.design.widget.BottomNavigationView>
I got this solution from this link:
Selected tab's color in Bottom Navigation View
But when I run the app it crashes with error "unable to inflate navigation bar". What am I doing wrong? Any help would be appreciated.
Update:
I tried the same thing by creating selector file in drawable file but unfortunately it also doesn't work.
Try this:-
Set item.setCheckable(true) inside onNavigationItemSelected()
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
item.setCheckable(true);
mTextMessage.setText(R.string.title_home);
return true;
}
return false;
}
I have NavigationView in my DrawerLayout and let's say it has simple menu
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/nav_settings"
android:icon="#drawable/ic_settings_black_24dp"
android:title="#string/title_settings"/>
</menu>
Now I set listener for click:
mNavigationVeiw.setOnNavigationItemSelected(this);
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_settings:
SettingsActivity.startActivity(this);
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
return false;
}
The problem is that I don't see ripple effect. When I long press on item, the ripple is showing, but with click it's not working. I think the problem is that I open Activity after click instead of replacing fragments, and my menu should have addition options. How can I fix that?
EDIT
Everything works fine when I set <group android:checkableBehavior="single"> but in my case it's not this behavior, cause I'm launching another activity and it should not check clicked item, because in this new Activity is back button on the top instead of access navigation drawer.
Add itemBackground into NavigationView inside your xml file the following attribute:
app:itemBackground="#drawable/ripple_navigation_selector"
Also, inside the drawable-v21 folder, add ripple_navigation_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/submit_btn_ripple_color" >
<item android:drawable="#color/accentColor" />
<item
android:id="#android:id/mask"
android:drawable="#android:color/white" />
</ripple>
I needed to add bottom navigation bar in my app, which I was able to do very well using the bottombar library that I found in github.
However, another requirement is to change the icons of the bottombar when I click on it. I have not been able to achieve this. Can anyone help me how can I achieve the
My implementation is as follows
bottomBar = BottomBar.attach(view,savedInstanceState);
bottomBar.useDarkTheme(false);
bottomBar.setItemsFromMenu(R.menu.bottom_home_menu, new OnMenuTabSelectedListener() {
#Override
public void onMenuItemSelected(#IdRes int menuItemId) {
switch (menuItemId){
case R.id.menu_home:
Snackbar.make(view,"Home tab",Snackbar.LENGTH_SHORT).show();
break;
case R.id.menu_to_do:
Snackbar.make(view,"To Do tab",Snackbar.LENGTH_SHORT).show();
break;
case R.id.menu_add_books:
Snackbar.make(view,"Add",Snackbar.LENGTH_SHORT).show();
break;
case R.id.menu_notification:
Snackbar.make(view,"Notification",Snackbar.LENGTH_SHORT).show();
break;
case R.id.menu_profile:
Snackbar.make(view,"Profile",Snackbar.LENGTH_SHORT).show();
break;
}
}
});
As per a tutorial that i had seen, it said to add a menu and I did in as shown below. This is the exact code that I have used in the my demo.
Its mentioned in the below snippet.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/menu_home"
android:icon="#drawable/icon_home_hdpi"
android:title="Home"/>
<item
android:id="#+id/menu_to_do"
android:icon="#drawable/icon_todo_hdpi"
android:title="To Do"/>
<item
android:id="#+id/menu_add_books"
android:icon="#drawable/icon_add_hdpi"
android:title="Add"/>
<item
android:id="#+id/menu_notification"
android:icon="#drawable/icon_notification_hdpi"
android:title="Notification"/>
<item
android:id="#+id/menu_profile"
android:icon="#drawable/icon_profile_hdpi"
android:title="Profile"/>
</menu>
I don't have the library to test, but probably you can set for the original icon a StateListDrawable, with different images for different states.
You just need to add this file as drawable and give this xml as Image Background.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/numpad_button_bg_selected" android:state_selected="true"></item>
<item android:drawable="#drawable/numpad_button_bg_pressed" android:state_pressed="true"></item>
<item android:drawable="#drawable/numpad_button_bg_normal"></item>
</selector>
Can you please tell me how can I create an android menu item using android setting icon?
Here is a list of the standard icons. I don't see a "settings" icon. Perhaps you mean "Preferences" (ic_menu_preferences)?
You can set the icon programmatically like this:
menu.add(0, MENU_QUIT, 0, "Quit").setIcon(R.drawable.menu_quit_icon);
You can also set it in your xml layout like this:
<item android:id="#+id/save_button"
android:icon="#android:drawable/ic_menu_save"
android:title="Save Image"/>
Creating Menus in Android
You can see all the icons in the android SDK forder:
_your_install_path_\android-sdk\platforms\android-10\data\res\drawable-hdpi\
and then get a reference to them with:
android.R.drawable.ic_menu_preferences
just like it was your drawable.
Add a new Vector Asset.
File -> New -> Vector Asset.
Click on the icon to change it.
Select the icon you want (e.g. search for "setting").
Adjust other settings.
Use that new Vector Asset in your xml.
android:logo="#drawable/ic_settings_white_24dp"
Party!
If you want to handle the event, just try this on your activity
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// action with ID action_refresh was selected
case android.R.drawable.ic_popup_sync:
Toast.makeText(this, "ic_popup_sync selected", Toast.LENGTH_SHORT)
.show();
break;
default:
break;
}
return true;
}
And in your menu folder use something like this:
<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="com.example.test.app.MainActivity"
>
<item android:id="#+id/action_settings1"
android:icon="#drawable/abc_ic_search"
android:title="Find Location"
android:orderInCategory="100"
app:showAsAction="ifRoom" />
<item android:id="#+id/save_button"
android:icon="#android:drawable/ic_menu_save"
android:title="Save Image"/>
<item android:id="#+id/refresh"
android:icon="#android:drawable/ic_popup_sync"
android:title="Refresh"/>
</menu>