Custom Android TabWidget with Badges

Written by on August 16, 2011 in Dev Blog - 11 Comments

For an android app I’m working on I needed to present badges for tabs much like on the iPhone. I looked around for a bit but could not find any good solution for this. It seems the android SDK does not provide this feature out of the box. At least I could not find it. So I had a go at writing a custom TabWidget for this nifty feature.

I’m sure it can be made to look even better with some work. The icon is not the most pretty image and should probably be replaced. Called badge.png in the source files.

I used a singleton class BadgeTabManager to manage the tabs and get access to them from anywhere in the app. I guess this approach could be changed if several tabwidgets need to be used at the same time.

The badges are set by a simple call:

BadgeTabManager.getInstance().setBadgeAtIndex(5, 2);

The BadgeTabWidget looks like this:

/*
 * Copyright (C) 2011 Nilisoft
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.nilisoft.examples.badgetabs;

import java.util.HashMap;

import com.nilisoft.examples.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TabWidget;

public class BadgeTabWidget extends TabWidget{

	HashMap map;

	public BadgeTabWidget(Context context) {
		super(context);

		map = new HashMap();

	}

	public BadgeTabWidget(Context c, AttributeSet set){
		super(c, set);

		map = new HashMap();
	}

	public int getBadgeNumAtIndex(int index){
		Badge b = map.get(index);
		if (b == null){
			return 0;
		}
		else{
			return b.getNum();
		}
	}

	public void setBadgeAtIndex(int num, int index){
		Badge b = map.get(index);
		if (b == null){
			b = new Badge();
			map.put(index, b);
		}
		b.setNum(num);
public void setBadgeAtIndex(int num, int index){
		Badge b = map.get(index);
		if (b == null){
			b = new Badge();
			map.put(index, b);
		}
		b.setNum(num);

		// should probably use some other way to update the view (repaint the tabs) but this works...
		this.getChildAt(index).setVisibility(View.INVISIBLE);
		this.getChildAt(index).setVisibility(View.VISIBLE);
	}

	}

	@Override
	protected boolean drawChild (Canvas canvas, View child, long drawingTime){
		boolean b = super.drawChild(canvas, child, drawingTime);

		// figure out our index in the tabs, need it for the badge number
		int index = 0;
		for(int i=0; i < this.getTabCount(); i++){
			if (this.getChildAt(i) == child){
				index = i;
				break;
			}
		}

		int num = this.getBadgeNumAtIndex(index);

		if (num > 0){
			Bitmap src = BitmapFactory.decodeResource(this.getResources(),R.drawable.badge);
			Bitmap badge = Bitmap.createScaledBitmap(src, 24, 19, true);

			int x =  child.getRight()-badge.getWidth()-5;

			canvas.drawBitmap(badge, x, 0, new Paint());

			Typeface face = Typeface.create("Verdana", Typeface.BOLD);
			Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
			paint.setTypeface(face);
			paint.setTextSize(12);
			paint.setARGB(255, 255, 255, 255);

			String text = ""+num;
			Rect bounds = new Rect();
			paint.getTextBounds(text, 0, text.length(), bounds);

			canvas.drawText(
					text,
					(x+badge.getWidth()/2)-bounds.width()/2,
					// -1 here because the badge icon is looking as it does with some
					// more space at the bottom for shadows, might need change if the
					// size of the icon is changed
					(badge.getHeight()/2)+bounds.height()/2 -2,
					paint);

		}

		return b;
	}

	private class Badge {
		int num;

		public Badge(){
			num = 0;
		}

		public void setNum(int num){
			this.num = num;
		}

		public int getNum(){
			return num;
		}

	}

}

And the full source code the for example project can be downloaded here: BadgeTabs

Enjoy! And please let me know if you find this useful in any of your apps.

The end result looks like this:

About the author

11 Replies to Custom Android TabWidget with Badges

  1. Ganesh

    August 19, 2011 • 8:35 am

    Great Work. It is very useful for my shopping cart application, where on cart icon in tab bar I am showing no of items added. You saved my day. Thanks a tons.

  2. NBS

    August 21, 2011 • 10:36 pm

    Nice work. Thanks for the source. It was really help to my project

  3. Vivek

    September 14, 2011 • 8:07 am

    Great Work….its useful for me as well. But i am facing one problem. i want to show badges in two line(eg: Item then below item amount should be shown) I am passing the string with \n but its not showing in 2 line.

    • Nilisoft

      September 14, 2011 • 8:12 am

      Hmm, the draw text method on the canvas probably do not take newlines into consideration. You will have to actually draw two separate lines yourself, and increase the y coordinate on the second line. (And use a badge icon that actually fits two lines or the text will be drawn outside it).

      So simply add another drawText call for your second line should work…

  4. Vivek

    September 14, 2011 • 10:00 am

    Hi Nilisoft ,

    Thanks you are really awosme.

  5. wangpeng

    September 19, 2011 • 12:19 am

    cool,thank you very much

  6. Rao Venu

    November 25, 2011 • 8:08 pm

    Thanks for this example. It worked straight out of the box.

  7. Balu....

    December 24, 2011 • 8:42 am

    I love you man……….
    Thank you very much.

  8. ky

    December 29, 2011 • 2:23 am

    good,nick work

  9. mount

    March 1, 2012 • 6:19 pm

    Disconnected full source code download link

    Please revert download link…

    plz…!

  10. Nilisoft

    March 1, 2012 • 7:47 pm

    The download link should now work again. When moving sites the old links did not work very good. Should be better now!

Leave a Reply

Latest apps | Projects

  • Ljushults HBF
  • My Advent Calendar
  • My Gourmet Recipes
  • iCORNR
  • Hammerfall App