Android官方BottomNavigationView添加Badge(角标)

xiaoxiao2021-02-28  56

Google在Android API24添加了实现底部导航的BottomNavigationView,还算是比较良心的,相信做过类似功能的老铁对开源的BottomNavigationBar一定不会感到陌生,这个开源项目很好的实现了我们所需要的功能,包括我今天重点要说的添加角标Badge,它添加Badge的方式是在创建底部导航按钮的时候就设置了Badge:

bottomNavigationBar .addItem(new BottomNavigationItem(R.drawable.ic_error, "主页").setBadgeItem(faultBadgeItem)) .addItem(new BottomNavigationItem(R.drawable.ic_assignment, "通知").setBadgeItem(maintainBadgeItem)) .addItem(new BottomNavigationItem(R.drawable.ic_notifications, "消息").setBadgeItem(announcementBadgeItem)) .addItem(new BottomNavigationItem(R.drawable.ic_forum, "我的").setBadgeItem(imBadgeItem)) .initialise();

但是API24的BottomNavigationView是通过Menu的形式创建的,我们无法在它创建的时候就设置Badge,必须获取到每一个导航按钮Item所在的View,才能够添加上去。当然方法不是绝对的,之前看过看到一篇文章是通过在顶级容器上加入小红点,调整位置,伪装成和控件一体的方式实现,我还是觉得太过复杂,然后就看了一下BottomNavigationView的源码还是有所发现。

1.由于是通过Menu的方式创建,所以要把得到的MenuView添加进去,在构造方法中发现:

public BottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ThemeUtils.checkAppCompatTheme(context); // Create the menu mMenu = new BottomNavigationMenu(context); mMenuView = new BottomNavigationMenuView(context); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.gravity = Gravity.CENTER; mMenuView.setLayoutParams(params); mPresenter.setBottomNavigationMenuView(mMenuView); mPresenter.setId(MENU_PRESENTER_ID); mMenuView.setPresenter(mPresenter); mMenu.addMenuPresenter(mPresenter); mPresenter.initForMenu(getContext(), mMenu); // Custom attributes TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs, R.styleable.BottomNavigationView, defStyleAttr, R.style.Widget_Design_BottomNavigationView); if (a.hasValue(R.styleable.BottomNavigationView_itemIconTint)) { mMenuView.setIconTintList( a.getColorStateList(R.styleable.BottomNavigationView_itemIconTint)); } else { mMenuView.setIconTintList( createDefaultColorStateList(android.R.attr.textColorSecondary)); } if (a.hasValue(R.styleable.BottomNavigationView_itemTextColor)) { mMenuView.setItemTextColor( a.getColorStateList(R.styleable.BottomNavigationView_itemTextColor)); } else { mMenuView.setItemTextColor( createDefaultColorStateList(android.R.attr.textColorSecondary)); } if (a.hasValue(R.styleable.BottomNavigationView_elevation)) { ViewCompat.setElevation(this, a.getDimensionPixelSize( R.styleable.BottomNavigationView_elevation, 0)); } int itemBackground = a.getResourceId(R.styleable.BottomNavigationView_itemBackground, 0); mMenuView.setItemBackgroundRes(itemBackground); if (a.hasValue(R.styleable.BottomNavigationView_menu)) { inflateMenu(a.getResourceId(R.styleable.BottomNavigationView_menu, 0)); } a.recycle(); addView(mMenuView, params); if (Build.VERSION.SDK_INT < 21) { addCompatibilityTopDivider(context); } mMenu.setCallback(new MenuBuilder.Callback() { @Override public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { if (mReselectedListener != null && item.getItemId() == getSelectedItemId()) { mReselectedListener.onNavigationItemReselected(item); return true; // item is already selected } return mSelectedListener != null && !mSelectedListener.onNavigationItemSelected(item); } @Override public void onMenuModeChange(MenuBuilder menu) {} }); }

上边有两句关键代码:mMenuView = new BottomNavigationMenuView(context); addView(mMenuView, params);因而我们可以获取到BottomNavigationView的子View,类型为BottomNavigationMenuView:

BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigation.getChildAt(0);

2.拿到BottomNavigationMenuView,我基本就确定了底部导航的几个按钮就是它的子VIew,不放心,再看BottomNavigationMenuView的源码,看了OnLayout就100%确定了,so我们可以拿到每个导航按钮所在的View了:

View view1 = menuView.getChildAt(0); View view1 = menuView.getChildAt(0); View view1 = menuView.getChildAt(0); ...

拿到各个ItemView就So easy了,那不就是在它上边添加文字嘛:

BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationView.getChildAt(0); BadgeView.Builder.newBuilder() .setTargetView(menuView.getChildAt(0)) .setBadgeCount(10) .setMargin(new Integer[]{0, 8, 24, 0}) .build(this); BadgeView.Builder.newBuilder() .setTargetView(menuView.getChildAt(1)) .setBadgeCount(2) .setMargin(new Integer[]{0, 8, 24, 0}) .build(this); BadgeView.Builder.newBuilder() .setTargetView(menuView.getChildAt(2)) .setBadgeCount(8) .setMargin(new Integer[]{0, 8, 24, 0}) .build(this);

代码比较简单,就不上了,最后贴个图

转载请注明原文地址: https://www.6miu.com/read-81833.html

最新回复(0)