BottomNavigationView图标显示异常及点击布局偏移问题求助
我来帮你搞定这两个BottomNavigationView的问题,结合你的代码给出具体可行的方案:
问题1:图标无法显示白色,仍为灰色/黑色
你在menu的每个item里单独设置了android:iconTint,但这个设置很可能被BottomNavigationView自身的默认图标着色规则覆盖了。正确的姿势是直接在BottomNavigationView的布局里统一控制图标颜色,或者用颜色选择器区分选中/未选中状态:
方案1:统一设置所有图标为白色
修改你的BottomNavigationView布局,添加app:itemIconTint="@color/cardview_light_background"属性,这样所有图标都会直接应用白色:
<android.support.design.widget.BottomNavigationView android:id="@+id/main_screen_botton_nav" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@color/colorPrimaryDark" app:itemTextColor="@color/cardview_light_background" app:itemIconTint="@color/cardview_light_background" <!-- 新增这行 --> app:layout_behavior=".Common.BottomNavigationBehavior" app:menu="@menu/mainscreen_bottomnav" />
同时可以移除menu item里的android:iconTint属性,避免样式冲突:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/main_screen_home" android:icon="@drawable/home" android:title="Home" app:showAsAction="ifRoom" /> <!-- 其他item同理,删除android:iconTint属性 --> </menu>
方案2:区分选中/未选中的图标颜色(可选)
如果你希望选中的图标是白色,未选中的是浅灰色,可以创建一个颜色选择器文件(比如res/color/bottom_nav_icon_color.xml):
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/cardview_light_background" android:state_checked="true" /> <item android:color="@color/gray_light" android:state_checked="false" /> </selector>
然后在BottomNavigationView布局中引用这个选择器:
app:itemIconTint="@color/bottom_nav_icon_color"
问题2:点击选中项后挤压其他图标(禁用Shift Mode)
当BottomNavigationView的item数量超过3个时,默认会开启Shift Mode——选中的item会放大文字和图标,挤压其他item的空间。要禁用这个模式,有两种靠谱的方法:
方法1:反射实现(兼容旧版Support库)
在你的MainActivity中添加一个工具方法,通过反射关闭Shift Mode:
private void disableShiftMode(BottomNavigationView view) { BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0); try { Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode"); shiftingMode.setAccessible(true); shiftingMode.setBoolean(menuView, false); shiftingMode.setAccessible(false); for (int i = 0; i < menuView.getChildCount(); i++) { BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i); // 移除shift模式的动态效果 item.setShifting(false); // 确保所有item的选中状态样式统一 item.setChecked(item.getItemData().isChecked()); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
然后在初始化BottomNavigationView时调用这个方法:
BottomNavigationView bottomNavigationView = findViewById(R.id.main_screen_botton_nav); bottomNavigationView.setOnNavigationItemSelectedListener(this); disableShiftMode(bottomNavigationView); // 新增这行调用
方法2:官方属性实现(推荐)
如果你使用的是AndroidX Material库(或者Support Library 28.0.0及以上版本),可以直接在布局里添加app:labelVisibilityMode="labeled"属性,这样所有item的文字会一直显示,同时自动禁用Shift Mode:
<android.support.design.widget.BottomNavigationView android:id="@+id/main_screen_botton_nav" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@color/colorPrimaryDark" app:itemTextColor="@color/cardview_light_background" app:itemIconTint="@color/cardview_light_background" app:labelVisibilityMode="labeled" <!-- 新增这行 --> app:layout_behavior=".Common.BottomNavigationBehavior" app:menu="@menu/mainscreen_bottomnav" />
这个方法更简洁,不需要反射,是官方推荐的解决方案。
内容的提问来源于stack exchange,提问作者Psypher

