Logicchip

Count Notification For Menu Item and Launcher Icon

Yes we can display Count Notification in action bar and launcher icon. Before creating Count Notification in launcher icon and action bar menu item we need to know some facts. First one is that the native method for creating Count Notification in android launcher icon is deprecated long time ago. The possible solution is to use phone manufactures or launcher application API’s. It’s very hard work, writing code for each manufactures and launcher applications including their API library files. This results in too bulky code, time lose and increase the size of the application. We can overcome these problems and difficulties by using ShortcutBadger Github . ShortcutBadger is a library that can do count notification in launcher icon irrespective of manufacture or launcher app if they support Count Notification. ShortcutBadger take care of converting our input into supported manufacture or launcher app Count Notification.




First add the dependency

dependencies {
compile 'me.leolin:ShortcutBadger:1.1.8'
}

Now we move on to code part

Just add

ShortcutBadger.applyCount(this, i);

I is the integer value set i=0 to disable the count. You can check more information in github.
Count Notification for menu item in actionbar.

1.Creating the icon

The icon must be a vector asset normal png or jpg won’t work. You can get free vector icons from flaticon .Here icon named ic_home is used, now create another xml file called ic_menu.xml to hold the ic_home file. To handle the count a class named Count is used it extents drawable. Set count using setCounting method set 0 to reset the count.

 

2.icon holder


The xml file called ic_menu holds the changes for icon. One thing is to keep in mind is that the id f all icon holder must be same, otherwise you have to create more counter classes.
Ic_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/ic_home"
        android:gravity="center" />

    <!-- set a place holder Drawable so android:drawable isn't null -->
    <item
        android:id="@+id/ic_badge"
        android:drawable="@drawable/ic_home" />
</layer-list>

 

3.counting


We created icon and icon holder now the counting part. Create a class name count then extent the class Drawable.Now we end up with a class file looks like this.

public class Count extends Drawable {
    @Override
    public void draw(Canvas canvas) {

    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return PixelFormat.UNKNOWN;
    }
}

Change the getOpticity to this

public int getOpacity() {
    return PixelFormat.UNKNOWN;
}

Create objects.

private Paint paint1, paint2, paint3;
private Rect rect1 = new Rect();
private String count1 = "";
private boolean draw1;

Create a constructor.

public Count(Context context) {
    float mTextSize = context.getResources().getDimension(R.dimen.badge_text_size);
    paint1 = new Paint();
    paint1.setColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorBadge));
    paint1.setAntiAlias(true);
    paint1.setStyle(Paint.Style.FILL);
    paint2 = new Paint();
    paint2.setColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorBadge));
    paint2.setAntiAlias(true);
    paint2.setStyle(Paint.Style.FILL);

    paint3 = new Paint();
    paint3.setColor(Color.WHITE);
    paint3.setTypeface(Typeface.DEFAULT);
    paint3.setTextSize(mTextSize);
    paint3.setAntiAlias(true);
    paint3.setTextAlign(Paint.Align.CENTER);
}

Editing draw method.

public void draw(Canvas canvas) {

        if (!draw1) {
            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 centerX = (width - radius - 1) +5;
        float centerY = radius -5;
        if(count1.length() <= 2){
            // Draw badge circle.
            canvas.drawCircle(centerX, centerY, (int)(radius+7.5), paint2);
            canvas.drawCircle(centerX, centerY, (int)(radius+5.5), paint1);
        }
        else{
            canvas.drawCircle(centerX, centerY, (int)(radius+8.5), paint2);
            canvas.drawCircle(centerX, centerY, (int)(radius+6.5), paint1);
//            canvas.drawRoundRect(radius, radius, radius, radius, 10, 10, paint1);
        }
        // Draw badge count text inside the circle.
        paint3.getTextBounds(count1, 0, count1.length(), rect1);
        float textHeight = rect1.bottom - rect1.top;
        float textY = centerY + (textHeight / 2f);
        if(count1.length() > 2)
            canvas.drawText("99+", centerX, textY, paint3);
        else
            canvas.drawText(count1, centerX, textY, paint3);
    }

Create another method setCount.

public void setCount(String count) {
    count1 = count;

    // Only draw a badge if there are notifications.
    draw1 = !count.equalsIgnoreCase("0");
    invalidateSelf();
}




setCounting method.

public static void setCounting(Context context, LayerDrawable icon, String count) {

    Count badge;

    // Reuse drawable if possible
    Drawable reuse = icon.findDrawableByLayerId(R.id.ic_badge);
    if (reuse != null && reuse instanceof Count) {
        badge = (Count) reuse;
    } else {
        badge = new Count(context);
    }

    badge.setCount(count);
    icon.mutate();
    icon.setDrawableByLayerId(R.id.ic_badge, badge);
}

The full code.

Count.java

public class Count extends Drawable {
    private Paint paint1, paint2, paint3;
    private Rect rect1 = new Rect();
    private String count1 = "";
    private boolean draw1;

    public Count(Context context) {
        float mTextSize = context.getResources().getDimension(R.dimen.badge_text_size);
        paint1 = new Paint();
        paint1.setColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorBadge));
        paint1.setAntiAlias(true);
        paint1.setStyle(Paint.Style.FILL);
        paint2 = new Paint();
        paint2.setColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorBadge));
        paint2.setAntiAlias(true);
        paint2.setStyle(Paint.Style.FILL);

        paint3 = new Paint();
        paint3.setColor(Color.WHITE);
        paint3.setTypeface(Typeface.DEFAULT);
        paint3.setTextSize(mTextSize);
        paint3.setAntiAlias(true);
        paint3.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    public void draw(Canvas canvas) {

        if (!draw1) {
            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 centerX = (width - radius - 1) +5;
        float centerY = radius -5;
        if(count1.length() <= 2){
            // Draw badge circle.
            canvas.drawCircle(centerX, centerY, (int)(radius+7.5), paint2);
            canvas.drawCircle(centerX, centerY, (int)(radius+5.5), paint1);
        }
        else{
            canvas.drawCircle(centerX, centerY, (int)(radius+8.5), paint2);
            canvas.drawCircle(centerX, centerY, (int)(radius+6.5), paint1);
//	        	canvas.drawRoundRect(radius, radius, radius, radius, 10, 10, paint1);
        }
        // Draw badge count text inside the circle.
        paint3.getTextBounds(count1, 0, count1.length(), rect1);
        float textHeight = rect1.bottom - rect1.top;
        float textY = centerY + (textHeight / 2f);
        if(count1.length() > 2)
            canvas.drawText("99+", centerX, textY, paint3);
        else
            canvas.drawText(count1, centerX, textY, paint3);
    }

    /*
    Sets the count (i.e notifications) to display.
     */
    public void setCount(String count) {
        count1 = count;

        // Only draw a badge if there are notifications.
        draw1 = !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;
    }


    public static void setCounting(Context context, LayerDrawable icon, String count) {

        Count badge;

        // Reuse drawable if possible
        Drawable reuse = icon.findDrawableByLayerId(R.id.ic_badge);
        if (reuse != null && reuse instanceof Count) {
            badge = (Count) reuse;
        } else {
            badge = new Count(context);
        }

        badge.setCount(count);
        icon.mutate();
        icon.setDrawableByLayerId(R.id.ic_badge, badge);
    }

}

 

4.Creating the menu item

Modify the menu file located in menu folder in your project.Add this to the menu.

<item
        android:id="@+id/menu1A"
        android:icon="@drawable/ic_menu"
        android:title="Notification"
        app:showAsAction="always" />

All the other items are below this.

5. Main class

A menu item object is created.Some screen shots.

 

 

 

 

 

 

 

 

public MenuItem menu1A;

Now the first part is the

 

Count Notification.java
import me.leolin.shortcutbadger.ShortcutBadger;
import static logicchip.iconchange.Count.setCounting;

public class CountNotification extends AppCompatActivity implements View.OnClickListener{
    public AppCompatButton icon99,icon0,menu99,menu0;
    public MenuItem menu1A;
    String a="0";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_icon);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        icon99=(AppCompatButton)findViewById(R.id.icon99);
        icon0=(AppCompatButton)findViewById(R.id.icon0);
        menu99=(AppCompatButton)findViewById(R.id.menu99);
        menu0=(AppCompatButton)findViewById(R.id.menu0);


        icon99.setOnClickListener(this);
        icon0.setOnClickListener(this);
        menu99.setOnClickListener(this);
        menu0.setOnClickListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_icon, menu);
        menu1A = menu.findItem(R.id.menu1A);
        LayerDrawable icon = (LayerDrawable) menu1A.getIcon();
        setCounting(this, icon, a);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()){
            case R.id.icon0:
                ShortcutBadger.applyCount(this, 0);break;
            case R.id.icon99:
                ShortcutBadger.applyCount(this,99);break;
            case R.id.menu0:
                LayerDrawable icon = (LayerDrawable) menu1A.getIcon();
                a="0";
                setCounting(this, icon, a);
                invalidateOptionsMenu();//for refreshing menu
                // break;
            case R.id.menu99:
                LayerDrawable icon2 = (LayerDrawable) menu1A.getIcon();
                a="99";
                setCounting(this, icon2, a);
                invalidateOptionsMenu();//for refreshing menu
                break;
        }
    }
}

Now for the Ui part of Count Notification.

activity_icon.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:id="@+id/content_icon"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="logicchip.iconchange.CountNotification">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="set icon count"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
                <android.support.v7.widget.AppCompatButton
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/icon99"
                    android:text="99"
                    android:layout_weight="1"/>

                <android.support.v7.widget.AppCompatButton
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="0"
                    android:id="@+id/icon0"
                    android:layout_weight="1"/>
        </LinearLayout>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="set menu count"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <android.support.v7.widget.AppCompatButton
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="99"
                android:id="@+id/menu99"
                android:layout_weight="1"/>

            <android.support.v7.widget.AppCompatButton
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="0"
                android:id="@+id/menu0"
                android:layout_weight="1"/>
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>
Exit mobile version