Android 在底部导航栏顶部显示徽章';s图标

Android 在底部导航栏顶部显示徽章';s图标,android,material-design,bottomnavigationview,Android,Material Design,Bottomnavigationview,我已经在我的应用程序中实现了底部导航视图,我已经查看了在图标顶部显示徽章的每个位置,如 我想知道这是否可能实现。感谢您的帮助。 谢谢。编辑2020: 使用来自物料组件的BottomNavigation,它提供 支持在物品上添加徽章和许多其他现成功能: 旧答案: 使用support library底部导航栏时,在菜单项上显示徽章/通知相当复杂。 然而,有简单的解决方案来完成它。比如 此库是底部导航栏的更高级版本。您可以使用这个代码片段在菜单项上设置一个徽章 bottomNavigation.s

我已经在我的应用程序中实现了底部导航视图,我已经查看了在图标顶部显示徽章的每个位置,如 我想知道这是否可能实现。感谢您的帮助。
谢谢。

编辑2020:

使用来自物料组件的
BottomNavigation
,它提供 支持在物品上添加徽章和许多其他现成功能:

旧答案:

使用support library底部导航栏时,在菜单项上显示徽章/通知相当复杂。 然而,有简单的解决方案来完成它。比如

此库是底部导航栏的更高级版本。您可以使用这个代码片段在菜单项上设置一个徽章

bottomNavigation.setNotification(notification, bottomNavigation.getItemsCount() - 1);
您将得到以下结果


使用支持库BottomNavigationView很困难。一个简单的解决方案是使用外部组件。 一个容易处理的问题是: 检查其文档非常简单:

BottomBarTab nearby = bottomBar.getTabWithId(R.id.tab_nearby);
nearby.setBadgeCount(5);

// Remove the badge when you're done with it.
nearby.removeBadge/();

作为@zxbin的回答。您可以检查并尝试以下代码

BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(this);
navigation.setSelectedItemId(R.id.navigation_store);
BottomNavigationMenuView bottomNavigationMenuView =
        (BottomNavigationMenuView) navigation.getChildAt(0);
View v = bottomNavigationMenuView.getChildAt(4); // number of menu from left
new QBadgeView(this).bindTarget(v).setBadgeNumber(5);

来源于

如果您只想使用股票
底部导航视图
而不使用第三方库,我是这样做的:

BottomNavigationMenuView bottomNavigationMenuView =
            (BottomNavigationMenuView) navigationView.getChildAt(0);
View v = bottomNavigationMenuView.getChildAt(3); 
BottomNavigationItemView itemView = (BottomNavigationItemView) v;

View badge = LayoutInflater.from(this)
            .inflate(R.layout.notification_badge, itemView, true);
下面是布局文件:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <TextView
        android:id="@+id/notifications.badge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|center_horizontal"
        android:layout_marginLeft="10dp"
        android:layout_marginStart="10dp"
        android:background="@drawable/notification_badge"
        android:gravity="center"
        android:padding="3dp"
        android:text="9+"
        android:textColor="@color/white"
        android:textSize="11sp" />
</merge>

然后只需按id查找
TextView
,然后设置文本。
@drawable/notification\u徽章
只是一个可绘制的圆形

您可以这样尝试:

文本视图放在底部导航视图中进行计数(是一个框架布局):


并将其样式设置为:

<style name="bottomMenu">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">@dimen/toolbarHeight</item>
    <item name="android:layout_gravity">center|bottom</item>
    <item name="android:background">@color/colorThird</item>
    <item name="itemBackground">@drawable/tabs_ripple</item>
    <item name="itemIconTint">@drawable/bottom_menu_item_color</item>
    <item name="itemTextColor">@drawable/bottom_menu_item_color</item>
    <item name="menu">@menu/bottom_menu</item>
</style>

<style name="bottomMenuSelectionsNumber">
    <item name="android:text">@string/bottomMenuSelectionsNumber</item>
    <item name="android:textSize">@dimen/appSecondFontSize</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:layout_width">@dimen/bottomMenuSelectionsNumberDim</item>
    <item name="android:layout_height">@dimen/bottomMenuSelectionsNumberDim</item>
    <item name="android:layout_gravity">right|bottom</item>
    <item name="android:layout_marginRight">@dimen/bottomMenuSelectionsNumberMarginR</item>
    <item name="android:layout_marginBottom">@dimen/bottomMenuSelectionsNumberMarginB</item>
    <item name="android:gravity">center</item>
    <item name="android:includeFontPadding">false</item>
    <item name="android:background">@drawable/bottom_menu_selections_number_bg</item>
</style>
fun setBadge(count: Int) {
    bottomNavigationView.getBadge(menuItemId)?.isVisible = count > 0
}

匹配父项
@尺寸/高度
中心|底部
@颜色/颜色第三
@可拉拔/凸耳波纹
@可绘制/底部菜单项颜色
@可绘制/底部菜单项颜色
@菜单/底部菜单
@string/bottomMenuSelectionsNumber
@尺寸/尺寸
@颜色/白色
@尺寸/底部菜单选择尺寸
@尺寸/底部菜单选择尺寸
右|底
@尺寸/底部菜单选择最小值
@尺寸/底部选单选择门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框门框
居中
假的
@可绘制/底部\u菜单\u选项\u编号\u背景
底部菜单\u选项\u编号\u bg

    <android.support.design.widget.BottomNavigationView android:id="@id/bottomMenu" style="@style/bottomMenu">
        <TextView android:id="@id/bottomMenuSelectionsNumber" style="@style/bottomMenuSelectionsNumber"/>
    </android.support.design.widget.BottomNavigationView>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/colorAccent"/>
    <corners android:radius="@dimen/cornerRadius"/>
</shape>

更新:现在是物料支持徽章,请参阅下面的更多内容

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_landing);

         addBadgeView();

    }

旧答案

根据@Tinashe的回答,我希望徽章显示为无编号的吼叫:

代码:

override-fun-onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
//位置=2
addBadge(职位历史记录)
}
/**
*将徽章(通知点)添加到底部栏
*@param位置获取徽章容器
*/
@SuppressLint(“私有资源”)
私人娱乐徽章(位置:Int){
//获取徽章容器(父级)
val bottomMenu=navigation.getChildAt(0)作为?BottomNavigationMenuView
val v=底部菜单?.getChildAt(位置)作为底部导航项视图
//从布局中为徽章充气
badge=从(此)开始的布局
.充气(右布局。徽标_布局,底部菜单,假)
//创建徽章布局参数
val badgeLayout:FrameLayout.LayoutParams=FrameLayout.LayoutParams(badge?.LayoutParams)。应用{
重力=重力。重心水平
topMargin=resources.getDimen(R.dimen.design\u bottom\u navigation\u margin).toInt()
//8dp
leftMargin=resources.getDimension(R.dimen.bagde_left_margin).toInt()
}
//使用布局参数将视图添加到底部栏
v?.addView(徽章、徽章布局)
}
badge_layout.xml(badge_大小=12dp)


和可绘制背景new_notification.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <corners android:radius="100dp"/>
    <solid android:color="#F44336"/>
</shape>

编辑2:
BottomNavigationView现在支持本机显示徽章,如文档中所述

bottomNavigation.getOrCreateBadge(menuItemId)


我也面临同样的问题,我不想使用图书馆

因此,我创建了一个名为
layout\u news\u badge
的自定义版面:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/badge_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView
        android:id="@+id/badge_text_view"
        android:layout_width="19dp"
        android:layout_height="19dp"
        android:textSize="11sp"
        android:textColor="@android:color/white"
        android:background="@drawable/news_bottom_nav_bg"
        android:layout_gravity="top"
        android:layout_marginTop="4dp"
        android:layout_marginStart="16dp"
        android:gravity="center"
        android:padding="2dp"
        tools:text="9+" />
</FrameLayout>
然后我用这两种方法创建了一个
BottomMenuHelper

public static void showBadge(Context context, BottomNavigationView 
    bottomNavigationView, @IdRes int itemId, String value) {
    removeBadge(bottomNavigationView, itemId);
    BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
    View badge = LayoutInflater.from(context).inflate(R.layout.layout_news_badge, bottomNavigationView, false);
    
    TextView text = badge.findViewById(R.id.badge_text_view);
    text.setText(value);
    itemView.addView(badge);
}

public static void removeBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
    BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
    if (itemView.getChildCount() == 3) {
        itemView.removeViewAt(2);
    }
}
然后,当我在活动中调用它时:

BottomMenuHelper.showBadge(this, mBottomNavigationView, R.id.action_news, "1");
编辑1:
通过建议添加改进

使用最新的材质依赖项,现在本机支持添加徽章 将此添加到build.gradle中

    implementation 'com.google.android.material:material:1.1.0-alpha09'
在布局中添加以下内容

<!-- The rest of your layout here ....-->

  <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:menu="@menu/bottom_nav_menu"
            />

那你就可以

     val navBar  = findViewById<BottomNavigationView>(R.id.bottom_navigation)
     navBar.getOrCreateBadge(R.id.action_add).number = 2
val navBar=findviewbyd(R.id.bottom\u导航)
navBar.getOrCreateBadge(R.id.action\u add).number=2
R.id.action\u add for you将是您要在其上放置徽章的菜单项的id。从提供给BottomNavigationView的菜单文件中选中它

确保应用程序主题位于theme.MaterialComponents中

您可以在样式或清单中检查它。 我的例子是这样的

     <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:statusBarColor" tools:targetApi="lollipop">@color/colorPrimary</item>
    </style>

@颜色/原色
@颜色/原色暗
@颜色/颜色重音
@颜色/原色

现在,BadgeDrawable已将Badge添加为AndroidX BottomNavigationView的一部分。

请试试这个

1) 为徽章创建xml文件(例如,notification_badge_view.xml)

4) 下面是addBadgeView方法

private void addBadgeView() {
        try {
            BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationBar.getChildAt(0);
            BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(0); //set this to 0, 1, 2, or 3.. accordingly which menu item of the bottom bar you want to show badge
            notificationBadge = LayoutInflater.from(LandingActivity.this).inflate(R.layout.view_notification_badge, menuView, false);
            itemView.addView(notificationBadge);
            notificationBadge.setVisibility(GONE);// initially badge will be invisible 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
注意:底部导航栏是您的底部栏视图

5) 通过以下方法刷新徽章以显示和隐藏

private void refreshBadgeView() {
        try {
            boolean badgeIsVisible = notificationBadge.getVisibility() != GONE;
            notificationBadge.setVisibility(badgeIsVisible ? GONE : VISIBLE);//makes badge visible and invisible 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
6) 当我们点击特定的底部栏页面时,通过下面的行来精细地隐藏

bottomNavigationBar.setOnNavigationItemSelectedListener(new 
BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) 
              {
                switch (menuItem.getItemId()) {
                    case R.id.bottom_bar_one:
                        //while moving to first fragment
                        notificationBadge.setVisibility(GONE);
                        break;
                    case R.id.bottom_bar_two:
                        //moving to second fragment
                        break;
                    case R.id.bottom_bar_three:
                        //moving to third fragment
                        break;
                }
                return true;
            }
        });

@阿贝尔的答案是最好的,除非你已经有一套复杂的主题,没有时间去改变它们

然而,如果a)你时间紧迫,如果你正在使用谷歌材料libra
fun setBadge(count: Int) {
    bottomNavigationView.getBadge(menuItemId)?.isVisible = count > 0
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/badge"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_gravity="top|center_horizontal"
        android:layout_marginStart="10dp"
        android:gravity="center"
        android:padding="3dp"
        app:srcCompat="@drawable/notification_badge" />
</FrameLayout>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/colorAccent" />
    <stroke
        android:width="2dp"
        android:color="@android:color/white" />
</shape>
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_landing);

         addBadgeView();

    }
private void addBadgeView() {
        try {
            BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationBar.getChildAt(0);
            BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(0); //set this to 0, 1, 2, or 3.. accordingly which menu item of the bottom bar you want to show badge
            notificationBadge = LayoutInflater.from(LandingActivity.this).inflate(R.layout.view_notification_badge, menuView, false);
            itemView.addView(notificationBadge);
            notificationBadge.setVisibility(GONE);// initially badge will be invisible 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
private void refreshBadgeView() {
        try {
            boolean badgeIsVisible = notificationBadge.getVisibility() != GONE;
            notificationBadge.setVisibility(badgeIsVisible ? GONE : VISIBLE);//makes badge visible and invisible 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
bottomNavigationBar.setOnNavigationItemSelectedListener(new 
BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) 
              {
                switch (menuItem.getItemId()) {
                    case R.id.bottom_bar_one:
                        //while moving to first fragment
                        notificationBadge.setVisibility(GONE);
                        break;
                    case R.id.bottom_bar_two:
                        //moving to second fragment
                        break;
                    case R.id.bottom_bar_three:
                        //moving to third fragment
                        break;
                }
                return true;
            }
        });
  BottomNavigationItemView itemView = (BottomNavigationItemView) ((BottomNavigationMenuView) mBottomNavigation.getChildAt(0)).getChildAt(2);
  View badge = LayoutInflater.from(this).inflate(R.layout.navigation_dot, itemView, false);
  itemView.addView(badge);
// to remove
bottomNavigationView.removeBadge(R.id.action_settings)

// to add
bottomNavigationView.getOrCreateBadge(R.id.action_settings).apply {
    //if you want to change other attributes, like badge color, add a number, maximum number (a plus sign is added, e.g. 99+)
    number = 100
    maxCharactersCount = 3
    backgroundColor = ContextCompat.getColor(context, R.color.color_red)
}
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/solid_red_base" />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/badge_frame_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="11dp"
android:layout_gravity="center_horizontal">

<TextView
    android:id="@+id/badge_text_view"
    android:layout_width="12dp"
    android:layout_height="12dp"
    android:textSize="11sp"
    android:textColor="@android:color/white"
    android:background="@drawable/message_badge"
    android:layout_gravity="top"
    android:layout_centerHorizontal="true"
    android:padding="2dp"/> </RelativeLayout>
 public static void showBadge(Context context, BottomNavigationView
        bottomNavigationView, @IdRes int itemId, String value) {
    BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
    View badge = LayoutInflater.from(context).inflate(R.layout.message_notification_badge, bottomNavigationView, false);

    TextView text = badge.findViewById(R.id.badge_text_view);
    text.setText(value);
    itemView.addView(badge);
}

 public static void removeBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
    BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
    if (itemView.getChildCount() == 4) {
        itemView.removeViewAt(4);
    }
}
navBottomView = ((AppCompatActivity)this.context).findViewById(R.id.nav_view);
  BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
  if (badgeDrawable == null)
      navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
int previousValue = badgeDrawable.getNumber();
badgeDrawable.setNumber(previousValue + item.getQuantidade());
import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.bottomnavigation.BottomNavigationView;
btnAddCarrinho.setOnClickListener(v -> {
            navBottomView = ((AppCompatActivity) this.context).findViewById(R.id.nav_view);
            BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
            if (badgeDrawable == null) {
                navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
            } else {
                int previousValue = badgeDrawable.getNumber();
                badgeDrawable.setNumber(previousValue + item.getQuantidade());
            }
        });