Android Tablayout tabs with notification badge like whatsApp

Arjun sharma picture Arjun sharma · Aug 12, 2015 · Viewed 38.5k times · Source

I want to implement notification badge with android.support.design.widget.TabLayout. I had tried my best effort to implement it but fails.

Any help would by greatly appreciated.

Answer

mikepenz picture mikepenz · Nov 8, 2016

EDIT: UPDATE

With the newest release of the Material Components, the Android team now offers an official BadgeDrawable to be used on the TabLayout to achieve the asked result. It is part of the v1.1.0-alpha07 update. https://github.com/material-components/material-components-android/releases/tag/1.1.0-alpha07

The usage is very simple and can be done as following:

tabLayout.getTabAt(0).showBadge().setNumber(1);

See the integration in the material components demo app: https://github.com/material-components/material-components-android/commit/111cd001f5302bd6899f181ab7ccea2fd4002f63#diff-bf3e9a8a208f0ecab05088823fba99c4R239


OLD ANSWER

I tried some of the above mentioned solutions, but they did not deliver proper results. If you take a closer look in the TabLayout implementation you will realize that the TabView will try to get the textView and iconView from the CustomView if applied.

So instead of doing some hacky implementations I rather came up with a layout equal to the one from the original TabView but an additional view which can have a badge.

So you will need the badged_tab.xml layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        android:layout_marginTop="4dp">

        <ImageView
            android:id="@android:id/icon"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:scaleType="centerInside" />

        <TextView
            android:id="@android:id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:gravity="center"
            android:maxLines="2" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/badgeCotainer"
        android:layout_width="wrap_content"
        android:layout_height="16dp"
        android:layout_marginStart="12dp"
        android:background="@drawable/notifications_background"
        android:gravity="center"
        android:minWidth="16dp"
        android:visibility="gone">

        <TextView
            android:id="@+id/badge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAlignment="center"
            android:textColor="#fff"
            android:textSize="10sp" />
    </LinearLayout>
</RelativeLayout>

And some sort of notification background:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/red" />
</shape>

When adding your tab programatically just call

tab.setCustomView(R.layout.badged_tab);

And then you can show / hide / set a badge cound at any time via:

if(tab != null && tab.getCustomView() != null) {
    TextView b = (TextView) tab.getCustomView().findViewById(R.id.badge);
    if(b != null) {
        b.setText(notifications + "");
    }
    View v = tab.getCustomView().findViewById(R.id.badgeCotainer);
    if(v != null) {
        v.setVisibility(View.VISIBLE);
    }
}