Create a BadgeDrawable class that draws a count of notification plus an eye-popping red background circle (like in the screenshot ).
Define a LayerDrawable in XML to set as the android:icon of our MenuItem. The bottom layer of the LayerDrawable is the MenuItem's icon (typically a .png), and the top layer is the BadgeDrawable.
Simulate querying the count of notifications in our Activity, update the BadgeDrawable's count, then call Activity#invalidateOptionsMenu() to force the ActionBar Menu to refresh.
Output will be
BadgeDrawable.java
public class BadgeDrawable extends Drawable {
private float mTextSize;
private Paint mBadgePaint;
private Paint mTextPaint;
private Rect mTxtRect = new Rect();
private String mCount = "";
private boolean mWillDraw = false;
public BadgeDrawable(Context context) {
mTextSize = context.getResources().getDimension(R.dimen.badge_text_size);
mBadgePaint = new Paint();
mBadgePaint.setColor(Color.RED);
mBadgePaint.setAntiAlias(true);
mBadgePaint.setStyle(Paint.Style.FILL);
mTextPaint = new Paint();
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
public void draw(Canvas canvas) {
if (!mWillDraw) {
return;
}
Rect bounds = getBounds();
float width = bounds.right - bounds.left;
float height = bounds.bottom - bounds.top;
// Position the badge in the top-right quadrant of the icon.
float radius = ((Math.min(width, height) / 2) - 1) / 2;
float centerX = width - radius - 1;
float centerY = radius + 1;
// Draw badge circle.
canvas.drawCircle(centerX, centerY, radius, mBadgePaint);
// Draw badge count text inside the circle.
mTextPaint.getTextBounds(mCount, 0, mCount.length(), mTxtRect);
float textHeight = mTxtRect.bottom - mTxtRect.top;
float textY = centerY + (textHeight / 2f);
canvas.drawText(mCount, centerX, textY, mTextPaint);
}
/*
Sets the count (i.e notifications) to display.
*/
public void setCount(int count) {
mCount = Integer.toString(count)
// Only draw a badge if there are notifications.
mWillDraw = count > 0;
invalidateSelf();
}
@Override
public void setAlpha(int alpha) {
// do nothing
}
@Override
public void setColorFilter(ColorFilter cf) {
// do nothing
}
@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
}
For /res/drawable/ic_menu_notifications.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/ic_notification"
android:drawable="@drawable/ic_action_email"
android:gravity="center" />
<!-- set a place holder Drawable so android:drawable isn't null -->
<item
android:id="@+id/ic_badge"
android:drawable="@drawable/ic_action_email" />
</layer-list>
public class HomeActivity extends Activity {
private int mNotificationsCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Run a task to fetch the notifications count
new FetchCountTask().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.home, menu);
// Get the notifications MenuItem and
// its LayerDrawable (layer-list)
MenuItem item = menu.findItem(R.id.action_notifications);
LayerDrawable icon = (LayerDrawable) item.getIcon();
// Update LayerDrawable's BadgeDrawable
Utils.setBadgeCount(this, icon, mNotificationsCount);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_notifications) {
// TODO: display unread notifications.
return true;
}
return super.onOptionsItemSelected(item);
}
/*
Updates the count of notifications in the ActionBar.
*/
private void updateNotificationsBadge(int count) {
mNotificationsCount = count;
// force the ActionBar to relayout its MenuItems.
// onCreateOptionsMenu(Menu) will be called again.
invalidateOptionsMenu();
}
/*
Sample AsyncTask to fetch the notifications count
*/
class FetchCountTask extends AsyncTask<Void, Void, Integer> {
@Override
protected Integer doInBackground(Void... params) {
// example count. This is where you'd
// query your data store for the actual count.
return 5;
}
@Override
public void onPostExecute(Integer count) {
updateNotificationsBadge(count);
}
}
}
Utility class Utils.java
public class Utils {
public static void setBadgeCount(Context context, LayerDrawable icon, int count) {
BadgeDrawable badge;
// Reuse drawable if possible
Drawable reuse = icon.findDrawableByLayerId(R.id.ic_badge);
if (reuse != null && reuse instanceof BadgeDrawable) {
badge = (BadgeDrawable) reuse;
} else {
badge = new BadgeDrawable(context);
}
badge.setCount(count);
icon.mutate();
icon.setDrawableByLayerId(R.id.ic_badge, badge);
}
}
You have to create a custom drawable for that (I let you find how to create one the way you want it). Lets call it myDrawable. Then in your menu xml file you reference it with:
This should be the approach to achieve this
Output will be
BadgeDrawable.java
For /res/drawable/ic_menu_notifications.xml
/res/menu/menu_home.xml
Now in the HomeActivity.java
Utility class Utils.java
Reference Link for Full Code
Follow this links,
http://www.viralandroid.com/2016/01/adding-badge-notification-count-to-android-actionbar-icon.htmlenter link description here
https://github.com/mikepenz/Android-ActionItemBadgeenter link description here
You have to create a custom drawable for that (I let you find how to create one the way you want it). Lets call it
myDrawable
. Then in your menu xml file you reference it with: