Android 给BottomNavigationView添加未读消息红点提示

开篇

  在开发Android应用中,为应用添加BottomNavigationBar是一件司空见惯的事情。为此,google团队在android.support.design包中就专门提供了快速实现BottomNavigationBar的控件:BottomNavigationView,而BottomNavigationView并没有提供显示未读消息红点提示功能。本文主要讲解如何在BottomNavigationView上实现显示未读消息红点提示功能。当然,市面上很多大神开源了第三方的BottomNavigationBar框架,这里暂不展开讨论。不过这里还是推荐一个优秀的BottomNavigationBar开源项目:https://github.com/Ashok-Varma/BottomNavigation

效果截屏

《Android 给BottomNavigationView添加未读消息红点提示》

立即体验

扫描以下二维码下载体验App(从0.2.3版本开始,体验App内嵌版本更新检测功能):

《Android 给BottomNavigationView添加未读消息红点提示》

JSCKit库传送门:https://github.com/JustinRoom/JSCKit

实施步骤

在添加未读消息红点提示之前,分析BottomNavigationView源码

  • 1、从构造函数着手
public BottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        ...
        mMenuView = new BottomNavigationMenuView(context);
        ...
        mPresenter.setBottomNavigationMenuView(mMenuView);
        ...
        if (a.hasValue(R.styleable.BottomNavigationView_menu)) {
            inflateMenu(a.getResourceId(R.styleable.BottomNavigationView_menu, 0));
        }
        ...
    }

a、创建BottomNavigationMenuView实例:mMenuView
b、 BottomNavigationPresenter绑定mMenuView
c、 调用方法inflateMenu(int resId)解析xml菜单文件

  • 2、inflateMenu(int resId)方法:
    public void inflateMenu(int resId) {
        mPresenter.setUpdateSuspended(true);
        getMenuInflater().inflate(resId, mMenu);
        mPresenter.setUpdateSuspended(false);
        mPresenter.updateMenuView(true);
    }

从方法字面上不难看出updateMenuView就是用来更新菜单视图的。

  • 3、updateMenuView(boolean cleared)方法:
    @Override
    public void updateMenuView(boolean cleared) {
        if (mUpdateSuspended) return;
        if (cleared) {
            mMenuView.buildMenuView();
        } else {
            mMenuView.updateMenuView();
        }
    }

它调用了mMenuView.buildMenuView()构建菜单视图,而mMenuView就是在BottomNavigationView构造函数中BottomNavigationPresenter绑定的BottomNavigationMenuView的实例。

  • 4、buildMenuView()方法:
    public void buildMenuView() {
        ...
        for (int i = 0; i < mMenu.size(); i++) {
            mPresenter.setUpdateSuspended(true);
            mMenu.getItem(i).setCheckable(true);
            mPresenter.setUpdateSuspended(false);
            BottomNavigationItemView child = getNewItem();
            mButtons[i] = child;
            child.setIconTintList(mItemIconTint);
            child.setTextColor(mItemTextColor);
            child.setItemBackground(mItemBackgroundRes);
            child.setShiftingMode(mShiftingMode);
            child.initialize((MenuItemImpl) mMenu.getItem(i), 0);
            child.setItemPosition(i);
            child.setOnClickListener(mOnClickListener);
            addView(child);
        }
    }

到这里,我们不难看出,每一个menu就是一个BottomNavigationItemView示例:

public class BottomNavigationItemView extends FrameLayout implements MenuView.ItemView {
}

所以,整个流程看下来,我们知道:
BottomNavigationView添加了一个BottomNavigationMenuView实例,而BottomNavigationMenuView实例添加了N个BottomNavigationItemView实例。
很明显,我们要给每个menu添加未读消息红点提示其实就是在BottomNavigationItemView实例上添加一个显示未读消息的view。

在BottomNavigationItemView上添加未读消息红点提示view

  • 1、找到BottomNavigationMenuView
        private BottomNavigationView navigation;
        BottomNavigationMenuView menuView = null;
        for (int i = 0; i < navigation.getChildCount(); i++) {
            View child = navigation.getChildAt(i);
            if (child instanceof BottomNavigationMenuView) {
                menuView = (BottomNavigationMenuView) child;
                break;
            }
        }
  • 2、找到BottomNavigationItemView并添加未读消息红点view
      if (menuView != null) {
            int dp8 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics());
            dotViews = new DotView[menuView.getChildCount()];
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView.LayoutParams params = new BottomNavigationItemView.LayoutParams(i == menuView.getChildCount() - 1 ? dp8 : dp8 * 2, 0);
                params.gravity = Gravity.CENTER_HORIZONTAL;
                params.leftMargin = dp8 * 3;
                params.topMargin = dp8 / 2;
                BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(i);
                DotView dotView = new DotView(this);
                itemView.addView(dotView, params);
                if (i < menuView.getChildCount() - 1) {
                    dotView.setUnReadCount(new Random().nextInt(20));
                }
                dotViews[i] = dotView;
            }
        }

运行后看效果。

这里是详细实现实例:
https://github.com/JustinRoom/JSCKit/blob/master/app/src/main/java/jsc/exam/jsckit/ui/BottomNavigationViewActivity.java

篇尾

  原创不易,给个爱心,谢谢!QQ:1006368252

勿问成功的秘诀为何,且尽全力做你应该做的事吧。——美华纳

    原文作者:SwitchLife
    原文地址: https://www.jianshu.com/p/c08ed0c6d31d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞