Android BottomNavigationView

童铭晨
2023-12-01

之前项目使用的底部导航按钮都是用 RadioGroup 包裹 RadioButton 配合状态选择器实现的。这种实现方式布局是很灵活的,实现虽然也简单,但是要做复杂点的效果还是比较麻烦。

Google 官方推荐的是 BottomNavigationView + menu

常用的方法有:
setOnItemSelectedListener 获取选择监听进行对应的界面显示

也可以配合 NavController 本质也是通过 setOnItemSelectedListener

getOrCreateBadge 可以轻松实现数字红点

高级点可以通过 navView.getChildAt(0).getChildAt(0..itemcount) 获取 NavigationBarItemView,
对单个 item 的图标及颜色自定义大小,代码示例:

NavigationBarMenuView menuView = (NavigationBarMenuView) binding.navView.getChildAt(0);
NavigationBarItemView itemView = (NavigationBarItemView) menuView.getChildAt(1);
itemView.setIconSize(100);
itemView.setTextColor(new ColorStateList(new int[][]{}, new int[]{}));

配合 setOnItemSelectedListener 就可以轻松实现某个item选中放大,取消选中还原的效果,
代码如下:

        binding.navView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                NavigationBarMenuView menuView = (NavigationBarMenuView) binding.navView.getChildAt(0);
                if (item.getItemId() == R.id.navigation_dashboard) {
                    NavigationBarItemView itemView = (NavigationBarItemView) menuView.getChildAt(1);
                    itemView.setIconSize(100);
                    itemView.setTextColor(new ColorStateList(new int[][]{}, new int[]{}));
                } else {
                    NavigationBarItemView itemView = (NavigationBarItemView) menuView.getChildAt(1);
                    itemView.setIconSize(menuView.getItemIconSize());
                    itemView.setTextColor(menuView.getItemTextColor());
                }
                return true;
            }
        });

setOnItemSelectedListener 配合 Lottie 可以轻松实现选中动画,代码示例:
 


    Context mContext;

    NavLottieUtils(BottomNavigationView navView) {
        mContext = navView.getContext().getApplicationContext();
        navView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                itemSelected(item, mLottieMapping.get(item.getItemId()));
                return true;
            }
        });
    }

    /**
     * 如果之前有item,则还原其图标
     */
    private MenuItem mLastItem;

    public void itemSelected(MenuItem item, String path) {
        if (mLastItem != null) {
            //还原之前的图标
            restoreIcon(mLastItem);
        }
        mLastItem = item;
        if (TextUtils.isEmpty(path)) {
            new Exception("path is empty").printStackTrace();
            return;
        }
        if (item == null) {
            new Exception("MenuItem is null").printStackTrace();
            return;
        }
        saveNavIcon(item);
        LottieDrawable drawable = new LottieDrawable();
        LottieTask<LottieComposition> task = LottieCompositionFactory
                .fromAsset(mContext, path);
        task.addListener(new LottieListener<LottieComposition>() {
            @Override
            public void onResult(LottieComposition result) {
                drawable.setComposition(result);
                item.setIcon(drawable);
                drawable.start();
                task.removeListener(this);
            }
        });
        task.addFailureListener(new LottieListener<Throwable>() {
            @Override
            public void onResult(Throwable result) {
                result.printStackTrace();
            }
        });
    }

    private void saveNavIcon(MenuItem item) {
        //保存之前的图标
        if (mIconMapping.get(item.getItemId()) == null) {
            mIconMapping.put(item.getItemId(), item.getIcon());
        }
    }

    /**
     * 未选中的icon
     */
    private Map<Integer, Drawable> mIconMapping = new HashMap<>();

    /**
     * 还原其之前的图标
     *
     * @param menuItem
     */
    private void restoreIcon(MenuItem menuItem) {
        Drawable drawable = mIconMapping.get(menuItem.getItemId());
        menuItem.setIcon(drawable);
    }


    private Map<Integer, String> mLottieMapping = new HashMap<>();

    /**
     * 添加资源映射
     *
     * @param navId
     * @param lottiePath
     */
    public void addLottieAssetMapping(int navId, String lottiePath) {
        mLottieMapping.put(navId, lottiePath);
    }

 类似资料:

相关阅读

相关文章

相关问答