Android 项目在使用androidx 或者 "support:design:28.0.0"依赖时,取消BottomNavigationView大于3个item的位移动画
最近新项目要使用底部导航BottomNavigationView控件,但是在底部item大于3个的时候就会有位移动画,我们需要禁用位移动画,(作为面向网络编程的程序员)我上网一搜索,复制粘贴过来:
/**
* 解决BottomNavigationView大于3个item时的位移
* @param view
*/
public static 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);
item.setShiftingMode(false);
item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Log.e("BNVHelper", "Unable to get shift mode field", e);
} catch (IllegalAccessException e) {
Log.e("BNVHelper", "Unable to change value of shift mode", e);
}
}
然后运行,but,并没有起作用,认真分析代码,思路就是要利用反射,把 mShiftingMode 字段设置为false , 点进源码搜索发现并没有这个字段。后来在之前项目中发现这个代码方法并没有问题,只是项目引用的support:design 版本不一样,原来Google在support:design:28.0.0的时候把一些组件的源码更改了(真坑啊。。。) 回到28版本的BottomNavigationItemView 源码中仔细阅读源码,发现了两个变量:labelVisibilityMode 和 isShifting 。在setCheck(boolean checked)方法中,当分析实验后发现只有当lableVisibility为1并且isShifting 为false时,才能达到我们的效果。源码如下:
public void setChecked(boolean checked) {
this.largeLabel.setPivotX((float)(this.largeLabel.getWidth() / 2));
this.largeLabel.setPivotY((float)this.largeLabel.getBaseline());
this.smallLabel.setPivotX((float)(this.smallLabel.getWidth() / 2));
this.smallLabel.setPivotY((float)this.smallLabel.getBaseline());
switch(this.labelVisibilityMode) {
case -1:
if (this.isShifting) {
if (checked) {
this.setViewLayoutParams(this.icon, this.defaultMargin, 49);
this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0);
} else {
this.setViewLayoutParams(this.icon, this.defaultMargin, 17);
this.setViewValues(this.largeLabel, 0.5F, 0.5F, 4);
}
this.smallLabel.setVisibility(4);
} else if (checked) {
this.setViewLayoutParams(this.icon, (int)((float)this.defaultMargin + this.shiftAmount), 49);
this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0);
this.setViewValues(this.smallLabel, this.scaleUpFactor, this.scaleUpFactor, 4);
} else {
this.setViewLayoutParams(this.icon, this.defaultMargin, 49);
this.setViewValues(this.largeLabel, this.scaleDownFactor, this.scaleDownFactor, 4);
this.setViewValues(this.smallLabel, 1.0F, 1.0F, 0);
}
break;
case 0:
if (checked) {
this.setViewLayoutParams(this.icon, this.defaultMargin, 49);
this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0);
} else {
this.setViewLayoutParams(this.icon, this.defaultMargin, 17);
this.setViewValues(this.largeLabel, 0.5F, 0.5F, 4);
}
this.smallLabel.setVisibility(4);
break;
case 1:
if (checked) {
this.setViewLayoutParams(this.icon, (int)((float)this.defaultMargin + this.shiftAmount), 49);
this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0);
this.setViewValues(this.smallLabel, this.scaleUpFactor, this.scaleUpFactor, 4);
} else {
this.setViewLayoutParams(this.icon, this.defaultMargin, 49);
this.setViewValues(this.largeLabel, this.scaleDownFactor, this.scaleDownFactor, 4);
this.setViewValues(this.smallLabel, 1.0F, 1.0F, 0);
}
break;
case 2:
this.setViewLayoutParams(this.icon, this.defaultMargin, 17);
this.largeLabel.setVisibility(8);
this.smallLabel.setVisibility(8);
}
this.refreshDrawableState();
this.setSelected(checked);
}
所以,我们可以这样写:
class BottomNavigationViewUtil {
companion object {
/**
* 解决BottomNavigationView大于3个item时的位移
* 针对com.android.support:design:28.0.0以上或andoidx中com.google.android.material:material:1.0.0-beta01以上
* @param view
*/
@SuppressLint("RestrictedApi")
fun disableShiftMode(view: BottomNavigationView) {
val menuView = view.getChildAt(0) as BottomNavigationMenuView
try {
menuView.labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED // 1
for (i in 0 until menuView.childCount) {
val item = menuView.getChildAt(i) as BottomNavigationItemView
item.setShifting(false)
}
} catch (e: Exception) {
Log.e("NavigationView", "Unable to get shift mode field", e)
}
}
}
}
最后,使用底部导航BottomNavigationView时先注意引入的support:design是哪个版本的,如果是support:design:28.0.0或者使用的是androix版本,可以用后面这种方法,反之用最上面的方法。
//===============================================================================================
参考博客:https://blog.csdn.net/qq_33707520/article/details/81941857