Android: 底部导航视图-更改选定项的图标

我已经在我的应用程序中添加了 BottomNavigationView,如。

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 _ 導航 _ 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 点击

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;
}
});

我想改变图标的底部导航选定的位置。当用户单击一个项目时,我们如何实现这个特性?

(如果用户单击一个项目,则图标变为另一个项目)

126775 次浏览

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 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:
}

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>

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.

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);

Good luck.

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.

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
}

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"
/>

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.

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.