Search This Blog

Wednesday, October 13, 2010

Experience - Customizing Android's Tab Indicator

I was displeased by the initial look-n-feel of the Tabs on my TabActivity. When I ran the app on the emulator the non-selected tabs had a nice gray background and the selected tab was white. No issue here, but when I ran the exact same app on my device all the backgrounds were white as well as the text on each tab. This was a horrible combination it was nearly impossible to see any part of the Tabs. A description that I like of this problem can be found here.

Below I have listed several ways that I tried to fix the problem as well as the final solution that I decided on.

1) Customize theme & xml for Tab.
I started off looking for a way to customize the xml on TabWidget, TabHost, and even TabHost.Tabspec. I found out that TabHost didn't have much. TabWidget looked promising as I could change the look-n-feel of the divider and the bottom strip. Two nice features but what about the tab indicator? I then looked at TabHost.TabSpec this seemed to be the most promising but I found no xml attributes to change. Still wanting to change the look with xml I started digging into the theme looking for a way to change the look of a tab indicator. I was operating under the impression that this was just a theme problem and I thought a simple customization to the theme and all TabWidgets would display properly. The best resource I found can be found here, however this did not solve my problem.

2) Accessing TabWidget's children in code.
The second approach I took after a quick Google search was to try Advance Tab's idea. I was able to successfully change the tab indicators in code using a line similar to the following:

final TextView tv = (TextView) tabWidget.getChildAt(i).findViewById(android.R.id.title);

tv.setTextColor(this.getResources().getColorStateList(R.color.text_tab_indicator));


Changing the look through code is less than ideal and calling TabWidget's getChildAt() method was definitely not how the designers intended to change the tab indicator. I was very happy to have made some progress. However, I still wanted to be able to change the look in xml, so this approach didn't really solve my problem either.

3) Building a view for Tab's Indicator.
After several attempts and time spent on things that produced less than desirable results, I realized I had overlooked something simple. The "ah ha" moment (as I like to call it) came when I took another look at the TabHost.TabSpec's setIndicator() method. Since API level 4 we have been able to create a view and set it as the tab indicator. I felt like this way was simplistic and easy.

Below is a quick overview of how I configured my tab indicator view.
I created a tabindicator.xml like the following:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/tabindicatorselector"
android:layout_width="fill_parent" android:layout_height="fill_parent">

<TextView android:id="@+id/title"
android:layout_below="@id/title" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" android:text="Title">
</TextView>
<ImageView android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"/>
</RelativeLayout>


The code in my TabActivity looks like this:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

View indicator1 = getLayoutInflater().inflate(R.layout.tabindicator, null);
TextView title1 = (TextView)indicator1.findViewById(R.id.title);
title1.setText(R.string.Tab1Title);

TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab1")
.setIndicator(indicator1)
.setContent(new Intent(this, TabGroup1Activity.class)));
}


I have left out some details, but hopefully this gives the basic idea on how I built my own tab indicator view. Good luck!

1 comment:

  1. Great Help. Thanks
    Got solution from here after lot of searching.

    ReplyDelete