Custom Android Tabs

Due to limitation of Android Tab component I created a custom TabWidget that I am using in couple different projects already. The widget allows us to  add custom background and use custom icons, tabs   can be Top/Bottom aligned.

Currently tabs can launch new Activity and  Dialog , when starting new Activity we can use  “startActivityForResult” so our tab will get a notification when other activity have finished.

This is not a perfect solution as there are some drawbacks to it but it suits me well so I will stick to it till something better comes along; Hint Android gurus we need to be able to start new activities inside existing tab with more customization.

Creating a Tab

There a two thing that a tab needs

  • Icon: either R.drawable.id or Drawable Object
  • An Activity set via Intent or Dialog
Tab homeTab=new Tab(context, "HOME");
homeTab.setIcon(R.drawable.home);
homeTab.setIconSelected(R.drawable.home_selected);
homeTab.setIntent(new Intent(context, CarmeLauncher.class));

What is a TabHost ?

TabHost host tabs and specify how they will be rendered , TabViewConfig is used to configure the TabHost

TabHost tabHost=new TabHost(
	new TabViewConfig()
	.context(context)
	.headerResourceId(R.drawable.tab_background_55)
	.separatorId(R.drawable.separator)
	.orientation(TabHost.Orientation.BOTTOM)
);

I use fluent interfaces or as some call it Builder pattern for configuring TabHost I think its straight forward and intuitive.

Binding tabs to Activity

public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//Our Tab provider
		TabHostProvider tabProvider=new CarmeTabProvider(this);
		TabHost tabHost=tabProvider.getTabHost("main");
		//This is the content of the tab
		tabHost.setCurrentView(R.layout.main);
		setContentView(tabHost.render());
}

To make tab selected we need to retrieve it using tab assigned TAG name in this case “HOME” before setContentView(tabHost.render()) is called.

Tab home=tabHost.getTab("HOME");
home.setSelected(true);
setContentView(tabHost.render());

Download/View Demo Project

TabWidgetDemo

Carme Project using tabs bottom aligned

36 thoughts on “Custom Android Tabs”

  1. Yes, I will make this a opensource project. Right now I am switching from Activity to using ActivityGroup for better performance. It will be hosted here.

  2. Hello

    Thanks for sharing code. but while running i had faced lot of problems.
    i have added all resources and done respective changes,now program is running.
    but its not showing any tab.
    please help me.

    Thanks
    Makrand

  3. Hi, Greg, I really like how your tab design looks! Great job.

    I also looked up the code on google code but couldnt find it. Any chance you can share it with me? Regards Christian

  4. Hey Greg,
    Your code looks great! Could you possibly do an export of a working project that uses your code and make it available for download on your google code site?

    Thanks for all your work! This looks very promising!

  5. No you should not have to, can you post what SKD you using and a stack trace from your Logcat. Also are you running the demo project TabWidgetDemo?
    Email me gregbugaj @@@ yahoo … com or post here if you have any specific questions?

  6. Hey,

    I have this problem when running the code for first time:

    09-17 23:09:33.552: ERROR/AndroidRuntime(781): Caused by: java.lang.NullPointerException
    09-17 23:09:33.552: ERROR/AndroidRuntime(781): at com.gregbugaj.tabwidget.TabWidgedLauncher.onCreate(TabWidgedLauncher.java:54)
    09-17 23:09:33.552: ERROR/AndroidRuntime(781): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
    09-17 23:09:33.552: ERROR/AndroidRuntime(781): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)

    And line 54 is: Tab home=tabHost.getTab(“HOME”);

    Can anyone help me?

  7. Make sure that you defined
    homeTab = new Tab(context, "HOME");
    homeTab.setIcon(R.drawable.home);
    //t1.setIconSelected(R.drawable.home_selected);
    homeTab.setIntent(new Intent(context, TabWidgetDemoLauncher.class));

    tabHost.addTab(homeTab);
    Also here is a complete Demo project http://www.gregbugaj.com/?p=117

  8. Hi,

    I’m trying to run your TabWidgetDemo in v1.6 of the SDK. Getting the following:

    D/AndroidRuntime( 824): Shutting down VM
    W/dalvikvm( 824): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
    E/AndroidRuntime( 824): Uncaught handler: thread main exiting due to uncaught exception
    E/AndroidRuntime( 824): java.lang.VerifyError: com.gregbugaj.tabwidgetdemo.TabWidgetDemoLauncher
    E/AndroidRuntime( 824): at java.lang.Class.newInstanceImpl(Native Method)
    E/AndroidRuntime( 824): at java.lang.Class.newInstance(Class.java:1472)
    E/AndroidRuntime( 824): at android.app.Instrumentation.newActivity(Instrumentation.java:1097)
    E/AndroidRuntime( 824): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2316)
    E/AndroidRuntime( 824): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
    E/AndroidRuntime( 824): at android.app.ActivityThread.access$2100(ActivityThread.java:116)
    E/AndroidRuntime( 824): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
    E/AndroidRuntime( 824): at android.os.Handler.dispatchMessage(Handler.java:99)
    E/AndroidRuntime( 824): at android.os.Looper.loop(Looper.java:123)
    E/AndroidRuntime( 824): at android.app.ActivityThread.main(ActivityThread.java:4203)
    E/AndroidRuntime( 824): at java.lang.reflect.Method.invokeNative(NativeMethod)
    E/AndroidRuntime( 824): at java.lang.reflect.Method.invoke(Method.java:521)
    E/AndroidRuntime( 824): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
    E/AndroidRuntime( 824): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
    E/AndroidRuntime( 824): at dalvik.system.NativeStart.main(Native Method)

  9. Hello,

    I’m really trying to get this to work but I’m having some problems. Originally after finally getting the two projects imported together and what I thought was properly defining the tabs like mentioned above, I tried it on my phone and got a force close error. When looking at the log it said the same error as Wouter Goossens’s posted above. I’m not sure what I’m doing wrong as I got that error after defining homeTab etc etc.

    I would really like to get this to work but am not sure what exactly am I doing wrong. I’ve followed every instruction I’ve found and still nothing. Is there a more precise step-by-step guide? or any other tips?

  10. Hi I’m trying to make my own custom tabwidget but its not working. I downloaded the code and run it but when try to make it work in my application it doesn’t work at all. It breaks on TabViewConfig and such. I’m getting errors telling me that they can’t be resolved. Am I missing a reference or something this is very strange

  11. Hi Greg,
    I tried to implement this code using the demo you supplied and I get the same error as everyone else. A screencast would be fantastic. I recommend using Jing for your screencast. Its quick, simple, and free. I use it for documentation all the time. I think your component sounds like just what I need, I just need to see if I happen to be missing anything.
    1. I imported both projects
    2. added the TabWidgedLauncher as a required project on the build path
    3. Corrected the project name in the TabWidgedLauncher .project file.
    I had to remove some overrides the compiler was complaining about but after that, it compiled but fails with the same error everyone else has.

    Please help!!!!

    Thanks in advance

  12. Hi Greg,

    I wanted to start by saying you have done great job with those tabs.
    I’m just starting with java and android so doing something like this is beyond my abilities.

    I want to use your tabwidget solution in my app I’m writing and I was wondering if it is possible for me to use. I wouldent fill right using it without asking first.

  13. But had one problom:if you have three Activity,then you will onCreat() init the “View v=tabHost.render();setContentView(v)”,there have a flash…

  14. I’ve created a Tabbar with 2 tab. In tab1 there is a button, click this button will open a new widow. I see when this window opened, tabbar will be hidden. But I want tabbar visible. How can I do it?

  15. Wow… really. That’s a so good looking tab setup I had to download the source and the images for safekeeping incase this site goes down at some point.

    REALLY good work.

  16. Unable to read D:\Android\android-sdk-windows\AndroidManifest.xml: java.io.FileNotFoundException: D:\Android\android-sdk-windows\AndroidManifest.xml (The system cannot find the file specified)

    com.android.sdklib.io.StreamException: java.io.FileNotFoundException: D:\Android\android-sdk-windows\AndroidManifest.xml (The system cannot find the file specified)
    at com.android.sdklib.io.FileWrapper.getContents(FileWrapper.java:92)
    at com.android.sdklib.xml.AndroidManifestParser.parse(AndroidManifestParser.java:608)
    at com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper.parse(AndroidManifestHelper.java:71)
    at com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper.parseForData(AndroidManifestHelper.java:171)
    at com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage.extractNamesFromAndroidManifest(NewProjectCreationPage.java:997)
    at com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage.access$16(NewProjectCreationPage.java:983)
    at com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage$3.widgetSelected(NewProjectCreationPage.java:461)
    at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473)
    at org.eclipse.jface.window.Window.runEventLoop(Window.java:825)
    at org.eclipse.jface.window.Window.open(Window.java:801)
    at org.eclipse.ui.internal.actions.NewWizardShortcutAction.run(NewWizardShortcutAction.java:135)
    at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
    at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584)
    at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501)
    at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:411)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473)
    at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405)
    at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369)
    at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221)
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1311)
    Caused by: java.io.FileNotFoundException: D:\Android\android-sdk-windows\AndroidManifest.xml (The system cannot find the file specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.(Unknown Source)
    at com.android.sdklib.io.FileWrapper.getContents(FileWrapper.java:90)
    … 42 more

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>