BottomNavigationView 实用技巧(去除自带移动动画)

控件使用 就不在此啰嗦了,很简单。

  • 分析原因
    1.BottomNavigationView,item大于3个的显示奇怪的情况,这个移动动画几乎都是不想要的。
    首先在BottomNavigationMenuView中,有一个全局变量:mShiftingMode,然后在创建Menu的时候buildMenuView()
public void buildMenuView() {
          ...
          mShiftingMode = mMenu.size() > 3;
          ...
}

当size>3时候,设为ture。
然后在BottomNavigationItemView,设置check的时候:

@Override
    public void setChecked(boolean checked) {
        ViewCompat.setPivotX(mLargeLabel, mLargeLabel.getWidth() / 2);
        ViewCompat.setPivotY(mLargeLabel, mLargeLabel.getBaseline());
        ViewCompat.setPivotX(mSmallLabel, mSmallLabel.getWidth() / 2);
        ViewCompat.setPivotY(mSmallLabel, mSmallLabel.getBaseline());
        if (mShiftingMode) {
            if (checked) {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
                iconParams.topMargin = mDefaultMargin;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(VISIBLE);
                ViewCompat.setScaleX(mLargeLabel, 1f);
                ViewCompat.setScaleY(mLargeLabel, 1f);
            } else {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER;
                iconParams.topMargin = mDefaultMargin;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(INVISIBLE);
                ViewCompat.setScaleX(mLargeLabel, 0.5f);
                ViewCompat.setScaleY(mLargeLabel, 0.5f);
            }
            mSmallLabel.setVisibility(INVISIBLE);
        } else {
            if (checked) {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
                iconParams.topMargin = mDefaultMargin + mShiftAmount;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(VISIBLE);
                mSmallLabel.setVisibility(INVISIBLE);

                ViewCompat.setScaleX(mLargeLabel, 1f);
                ViewCompat.setScaleY(mLargeLabel, 1f);
                ViewCompat.setScaleX(mSmallLabel, mScaleUpFactor);
                ViewCompat.setScaleY(mSmallLabel, mScaleUpFactor);
            } else {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
                iconParams.topMargin = mDefaultMargin;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(INVISIBLE);
                mSmallLabel.setVisibility(VISIBLE);

                ViewCompat.setScaleX(mLargeLabel, mScaleDownFactor);
                ViewCompat.setScaleY(mLargeLabel, mScaleDownFactor);
                ViewCompat.setScaleX(mSmallLabel, 1f);
                ViewCompat.setScaleY(mSmallLabel, 1f);
            }
        }

        refreshDrawableState();
    }

然后会根据shiftMode的值执行不同的逻辑,所以产生了这个动画效果。

官方没有对这个 字段暴露出修改的方法,所以可以通过反射的方式,间接修改这个字段。

public class BottomNavigationViewHelper {
    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);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (Exception e) {
            
        } 
    }
}

最后在使用BottomNavigationView的地方 调用:

bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomview);
// 去除动画效果
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

最后运行起来,移动动画消除了,还附带了一个很细微的抖动动画,超赞的有木有。

你可能感兴趣的:(BottomNavigationView 实用技巧(去除自带移动动画))