Display badge on top of bottom navigation bar's icon

I have implemented the bottom navigation view in my app and I have looked every where to display badges on top of the icons like this I was wondering whether this is even possible to implement. Any help is appreciated. Thank you.


If you just want to use a stock BottomNavigationView and no third party lib here's how I've done it:

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);

Then here's the layout file:

<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>

Then just find TextView by id and set text. @drawable/notification_badge is just a circle shape drawable


Adding badges is natively supported now, using the latest material dependency add this to your build.gradle

    implementation 'com.google.android.material:material:1.1.0-alpha09'

in your layout add this

<!-- 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"
            />

then you can just

     val navBar  = findViewById<BottomNavigationView>(R.id.bottom_navigation)
     navBar.getOrCreateBadge(R.id.action_add).number = 2

R.id.action_add for you would be the id of the menu item you want to put a badge on. Check it from the menu file you feed to the BottomNavigationView.

Make sure your app theme is in Theme.MaterialComponents

you can check it in styles or manifest. for this example mine was this

     <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>

Edit 2020:

Use BottomNavigation from material components instead, it gives support to add badges on items and many other features out of the box:

https://github.com/material-components/material-components-android/blob/master/docs/components/BottomNavigation.md

Old Answer:

When using support library Bottom Navigation bar, its quite complex to show a badge/notification on menu items. However there are easy solutions to get it done. Such as https://github.com/aurelhubert/ahbottomnavigation

This library is more advanced version of Bottom Navigation bar. And you can set a badge on menu item simply using this code snippet.

bottomNavigation.setNotification(notification, bottomNavigation.getItemsCount() - 1);

And you'll get following result

enter image description here


EDIT 2:
BottomNavigationView now supports showing badge natively, as said in the doc here.

bottomNavigation.getOrCreateBadge(menuItemId)


I was facing the same issue and I didn't want to use a library.

So I created a custom layout called layout_news_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>

TextView background(news_bottom_nav_bg):

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="?attr/colorPrimary" />
</shape>

Then I created a BottomMenuHelper with this 2 methods:

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);
    }
}

Then when I call it in my Activity:

BottomMenuHelper.showBadge(this, mBottomNavigationView, R.id.action_news, "1");

EDIT 1: Added improvement by suggestion jatin rana