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