Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Badge notification over drawer toggle in toolbar - Android

Tags:

I want to notify user about new unread message in the app which is accessible through navigation drawer. I was thinking about notification badge something similar Apple have but over drawer toggle in toolbar.

This is what I have now: This is what I have now

This is what I want: This is what I want

How can I achieve that?

like image 763
Soriyyx Avatar asked Oct 18 '15 17:10

Soriyyx


People also ask

How do I display the count of notifications in the toolbar icon in Android?

Right-click on drawable > new > vector asset > search for notification icon and select > finish. We are going to use this icon to show our notification count on top of it.

How do I get notification badge on app icon Android?

If you want to change badge with number, you can be changed in NOTIFICATION SETTING on the notification panel or Settings > Notifications > App icon badges > Select Show with number.

How do I set badge notifications?

1 Go to Settings menu > Notifications. 3 Toggle the switch to ensure the App icon badge feature has been enabled. You can choose to Show with or without number of notifications displayed on the badge.


2 Answers

enter image description here

enter image description here

I found this really cool BadgeDrawable class on the internet and you can add badge count to any drawable using this class. Please follow below steps.

Step 1: add below class to your project first.

import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.util.TypedValue;   /**  * Created by Admin on 2/25/2016.  */ public class BadgeDrawable extends Drawable {      private float mTextSize;     private Paint mBadgePaint;     private Paint mBadgePaint1;     private Paint mTextPaint;     private Rect mTxtRect = new Rect();      private String mCount = "";     private boolean mWillDraw = false;       public BadgeDrawable(Context context) {         mTextSize = dpToPx(context, 8); //text size         mBadgePaint = new Paint();         mBadgePaint.setColor(Color.RED);         mBadgePaint.setAntiAlias(true);         mBadgePaint.setStyle(Paint.Style.FILL);         mBadgePaint1 = new Paint();         mBadgePaint1.setColor(Color.parseColor("#EEEEEE"));         mBadgePaint1.setAntiAlias(true);         mBadgePaint1.setStyle(Paint.Style.FILL);          mTextPaint = new Paint();         mTextPaint.setColor(Color.WHITE);         mTextPaint.setTypeface(Typeface.DEFAULT);         mTextPaint.setTextSize(mTextSize);         mTextPaint.setAntiAlias(true);         mTextPaint.setTextAlign(Paint.Align.CENTER);     }      private float dpToPx(Context context, float value) {         Resources r = context.getResources();         float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, r.getDisplayMetrics());         return px;     }       @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.    /*Using Math.max rather than Math.min */ //        float radius = ((Math.max(width, height) / 2)) / 2;         float radius = width * 0.15f;         float centerX = (width - radius - 1) +10;         float centerY = radius -5;         if(mCount.length() <= 2){             // Draw badge circle.             canvas.drawCircle(centerX, centerY, radius+9, mBadgePaint1);             canvas.drawCircle(centerX, centerY, radius+7, mBadgePaint);         }         else{             canvas.drawCircle(centerX, centerY, radius+10, mBadgePaint1);             canvas.drawCircle(centerX, centerY, radius+8, 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);         if(mCount.length() > 2)         canvas.drawText("99+", centerX, textY, mTextPaint);         else         canvas.drawText(mCount, centerX, textY, mTextPaint);     }      /*      Sets the count (i.e notifications) to display.       */     public void setCount(String count) {         mCount = count;         // Only draw a badge if there are notifications.         mWillDraw = !count.equalsIgnoreCase("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;     } } 

Step 2: Now create a drawable (in my case it is ic_badge_drawable.xml). Then copy and paste below xml text.

<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">      <item android:id="@+id/ic_main_icon"         android:drawable="@drawable/ic_burger"         android:gravity="center" />       <!-- set a place holder Drawable so android:drawable isn't null -->     <item android:id="@+id/ic_badge"         android:drawable="@drawable/ic_burger" /> </layer-list> 

here you can pass any drawable for now, later we can pass any drawable to those. These are just like place holders.

Step 3: We have already setup everything. Now you can use below method to set badge count for any drawable.

 private Drawable setBadgeCount(Context context, int res, int badgeCount){         LayerDrawable icon = (LayerDrawable) ContextCompat.getDrawable(context, R.drawable.ic_badge_drawable);         Drawable mainIcon = ContextCompat.getDrawable(context, res);         BadgeDrawable badge = new BadgeDrawable(context);         badge.setCount(String.valueOf(badgeCount));         icon.mutate();         icon.setDrawableByLayerId(R.id.ic_badge, badge);         icon.setDrawableByLayerId(R.id.ic_main_icon, mainIcon);          return icon;     } 

Step 4: I used it as below to change my default burger icon.

setSupportActionBar(toolbar); getSupportActionBar().setHomeAsUpIndicator(setBadgeCount(this,R.drawable.ic_burger, 3)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowCustomEnabled(true);   // enable overriding the default toolbar layout getSupportActionBar().setDisplayShowTitleEnabled(false);// disable the default title element here (for centered title) 
like image 80
Tharindu Welagedara Avatar answered Sep 21 '22 15:09

Tharindu Welagedara


enter image description here

I have used simple TextView inside android.support.design.widget.AppBarLayout please check below complete code

MainActivity.java

import android.os.Bundle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.widget.TextView;  public class MainActivity extends AppCompatActivity {       private DrawerLayout mDrawerLayout;       @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          initViews();      }       private void initViews() {          mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);          setUpToolbar();      }       private void setUpToolbar() {          Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);          setSupportActionBar(toolbar);          final ActionBar ab = getSupportActionBar();          ab.setHomeAsUpIndicator(R.drawable.navigation_drawericon);          ab.setDisplayHomeAsUpEnabled(true);      }       @Override      public boolean onCreateOptionsMenu(Menu menu) {          getMenuInflater().inflate(R.menu.home_menu, menu);          return true;      }       @Override      public boolean onOptionsItemSelected(android.view.MenuItem item) {          switch (item.getItemId()) {              case android.R.id.home:                  mDrawerLayout.openDrawer(GravityCompat.START);                  return true;          }          return super.onOptionsItemSelected(item);      }       private void updateCounter(int count) {          ((TextView) findViewById(R.id.tv_nav_drawer_count)).setText(count + "");      }       public void closeDrawer() {          mDrawerLayout.closeDrawers();      }   } 

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>     <android.support.v4.widget.DrawerLayout         xmlns:android="http://schemas.android.com/apk/res/android"         android:id="@+id/drawer_layout"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:background="@android:color/white"         android:fitsSystemWindows="true">          <include layout="@layout/container_layout"/>          <android.support.design.widget.NavigationView             android:id="@+id/navigation_view"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:layout_gravity="start"             android:fitsSystemWindows="true">          </android.support.design.widget.NavigationView>       </android.support.v4.widget.DrawerLayout> 

container_layout.xml

<android.support.design.widget.CoordinatorLayout             xmlns:android="http://schemas.android.com/apk/res/android"             xmlns:app="http://schemas.android.com/apk/res-auto"             android:id="@+id/main_content"             android:layout_width="match_parent"             android:layout_height="match_parent">              <android.support.design.widget.AppBarLayout                 android:id="@+id/appbar"                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">                  <android.support.v7.widget.Toolbar                     android:id="@+id/toolbar"                     android:layout_width="match_parent"                     android:layout_height="?attr/actionBarSize"                     android:background="?attr/colorPrimary"                     app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>                   <TextView                     android:id="@+id/tv_nav_drawer_count"                     android:layout_width="15dp"                     android:layout_height="15dp"                     android:layout_marginLeft="30dp"                     android:layout_marginTop="-45dp"                     android:background="@drawable/menu_text_bg"                     android:gravity="center"                     android:text="10"                     android:textColor="@android:color/white"                     android:textSize="8dp"/>               </android.support.design.widget.AppBarLayout>              <FrameLayout                 android:id="@+id/home_frame_container"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_marginTop="?actionBarSize"/>           </android.support.design.widget.CoordinatorLayout> 

home_menu.xml

     <?xml version="1.0" encoding="utf-8"?>         <menu xmlns:android="http://schemas.android.com/apk/res/android"               xmlns:app="http://schemas.android.com/apk/res-auto">              <item                 android:id="@+id/menu_search"                 android:icon="@android:drawable/ic_menu_search"                 android:orderInCategory="101"                 android:title="Search"                 app:showAsAction="always"/>         </menu> 

menu_text_bg.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"         android:width="24dp"         android:height="24dp"         android:viewportHeight="24.0"         android:viewportWidth="24.0">     <path         android:fillColor="@android:color/holo_red_dark"         android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"/> </vector> 
like image 27
jaffar Avatar answered Sep 18 '22 15:09

jaffar