"support:design:28.0.0"或androidx使用BottomNavigationView时取消位移动画

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yuan7016/article/details/88311829

  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

猜你喜欢

转载自blog.csdn.net/yuan7016/article/details/88311829