美文网首页
BottomNavigationView 实用技巧(去除自带移动

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

作者: 米奇小林 | 来源:发表于2017-09-14 17:49 被阅读71次

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

    • 分析原因
      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 实用技巧(去除自带移动

          本文链接:https://www.haomeiwen.com/subject/qbgdsxtx.html