Custom Android Tabs

Written by

in

,

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

[nggallery id=2]

Comments

37 responses to “Custom Android Tabs”

  1. Luca Avatar
    Luca

    Cool! Is the source code of you project available?

    1. admin Avatar

      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. Danilo Avatar
    Danilo

    Hi, great work! Any news on the release of your project’s code?

    1. admin Avatar

      Hello guys,
      There is still more work to do on it but it is usable it will be mostly an implementation/performance fixes.

      Project is hosted on googlecode
      http://code.google.com/p/androidtabs/
      source will be uploaded sometimes today.

  3. Makrand Avatar

    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

  4. Christian S. Avatar
    Christian S.

    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

  5. Coyle L. McGuire Avatar

    Hey Greg,
    I would also be very glad if you could (re-)publish your code since I’m really interested
    in the custom Tabs…

    Rgds
    Coyle L. McGuire

  6. Matty Avatar
    Matty

    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!

    1. Greg Avatar

      Yes, I should do that this weekend. But if you like here is a link to a working demo project

  7. Wouter Goossens Avatar
    Wouter Goossens

    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?

    1. Greg Avatar

      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. Derek Avatar
    Derek

    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. laguiz Avatar
    laguiz

    same as Derek

  10. laguiz Avatar
    laguiz

    I have the sae with 1.5 :/

    1. Greg Avatar

      I will take a look at it this weekend

  11. Extreme Avatar
    Extreme

    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?

  12. base64 Avatar

    Hello! Is there any way to get the PSD files for those icons included in the project? Thanks! Please email them!

    1. Greg Avatar

      I don’t think that I have the psd for this files, I have found them on one of the icon websites.

  13. Crmurray1 Avatar
    Crmurray1

    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

    1. Greg Avatar

      I see people running into some problems with setting up the widget, so I have decided to make a screen cast asap.

  14. Par Avatar
    Par

    Hi, I cannot find the actual tabwidget library with the demo. Is it published elsewhere?

  15. Par Avatar
    Par

    Nevermind, I found it! 🙂 It is under http://code.google.com/p/androidtabs/source/checkout

    For anyone looking for the code under ‘downloads’, click the ‘source’ tab.

  16. Chris Hale Avatar
    Chris Hale

    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

  17. Toni Avatar
    Toni

    Same exception here…frustrating.

  18. Lizard Avatar
    Lizard

    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.

    1. Greg Avatar

      Thank you for you comment, also you can use in any project you like.

  19. Kay Avatar
    Kay

    I’ve just found a solution, that allows the same, with androids native tabhost, going to post an “tutorial” soon 🙂

    here is a Preview: http://images.sourceway.eu/android/betterTabs.jpg (its even possible without the Text below the icon, or just text… or whatever u want <3)

  20. Kay Avatar
    Kay

    http://www.sourceway.eu/ <- there you can find the tutorial =D

    its not nice but well, dont have a CMS or Blog setup there =D

  21. Kay Avatar
    Kay

    here is a new link, i’ve just installed wordpress and made a nice tutorial 😀

    http://sourceway.eu/wp/2010/06/android-tutorial-1-custom-tabs/

    (you may delete the post from June 7th, 2010 at 12:43 pm ^^)

    1. Greg Avatar

      Very nice tutorial.

  22. melody Avatar
    melody

    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…

  23. Piyush Avatar

    Thanks for tutorial.. very usefull..

  24. anticafe Avatar
    anticafe

    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?

  25. Anders Avatar
    Anders

    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.

  26. Pushpendra Sharma Avatar
    Pushpendra Sharma

    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 *