Search code examples
androidtabsandroid-actionbarandroid-3.0-honeycomb

Use different Color for different ActionBar.Tab


I want to have all tabs in ActionBar to have different Color Indicators, for example blue for tab 1, red for tab 2 etc.

To achieve that I did create different selectors for all colors and put them in different xmls in drawable. In style.xml I am calling them by

<style name="MyTheme" parent="AppBaseTheme">
<item name="android:actionBarTabStyle">@style/ActionBarTabStyleRed</item>
</style>
<style name="ActionBarTabStyleRed">
<item name="android:background">@drawable/tab_indicator_red</item>
</style>

I've created that style for different colors too. Now when I change the drawable or style to different color, it works. I can see colors being applied to tabs. But since all tabs are of same color, it didn't solve my purpose. I tried to set style of tabs in onTabSelected() but there's no method to do that.

Ultimately I tried to create different themes for different colors and tried to set them programtically in onTabSelected(), but then I got to know that theme must be set before setContentView().
So My questions is..How can I do that? Is there any way I can have different colors for different tab indicators???

Update:-
the drawable/tab_indicator_red.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@android:color/transparent" />
    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/tab_selected_red" />

    <!-- Focused states -->
    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused_red" />
    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_red" />

    <!-- Pressed -->
    <!--    Non focused states -->
    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_red" />
    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_red" />

    <!--    Focused states -->
    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_red" />
    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_red" />
</selector>

Solution

  • I think I have a starting point for you but it is a little bit fiddly. Setting up the action bar with the following code you can set the tabs to use you custom look:

      //...somewhere in oncreate
      ActionBar bar = getActionBar();
    
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    
        ActionBar.Tab tab1 = bar.newTab();
        TextView tv1 = createTab("Tab 1", R.drawable.firsttabdrawable);
        tab1.setCustomView(tv1);
        tab1.setTabListener(this);
        ActionBar.Tab tab2 = bar.newTab();
        tab2.setCustomView(createTab("Tab 2", R.drawable.secondTabDrawable));
        tab2.setTabListener(this);
        ActionBar.Tab tab3 = bar.newTab();
        tab3.setCustomView(createTab("Tab 3", R.drawable.thirdTabDrawable));
        tab3.setTabListener(this);
        ActionBar.Tab tab4 = bar.newTab();
        tab4.setCustomView(createTab("Tab 4", R.drawable.fourthTabDrawable));
        tab4.setTabListener(this);  
    
        bar.addTab(tab1);
        bar.addTab(tab2);
        bar.addTab(tab3);
        bar.addTab(tab4);
    

    createTab method as follows:

      private TextView createTab(String titleText, int tabBackgroundDrawableId)
    {
        TextView tv = new TextView(this);
        //set caption and caption appearance
        tv.setTextAppearance(this, R.style.MyDefaultTabTextAppearance);
        tv.setText(titleText);
        //set appearance of tab
        tv.setBackgroundResource(tabBackgroundDrawableId);
        tv.setLayoutParams(new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
        //Make sure all tabs have the same height
        tv.setMaxLines(2);
        tv.setMinLines(2);
    
        return tv;      
    }
    

    However the actionbar seems to add the tab view to a parent view that adds padding so for each one you need to remove it. I did this in the oncreate after the first code block like so:

      View view = (View) tv1.getParent();       
        LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams)view.getLayoutParams();
        view.setPadding(0, 0, 0, 0);
        view.setLayoutParams(lp);
    

    You may find a more graceful/straightforward way of doing this but as a starting point I thought it was worth posting.

    Hope this helps.

    ADDED:

    It may also be worth pointing out that if you have a more complicated layout for your tab you can inflate a layout xml file in the createTab method instead. For example using the following xml (mytab.xml):

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tabIcon"/>
    <TextView style="@style/MyDefaultTabTextAppearance"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/tabIcon"
        android:minLines="2"
        android:maxLines="2"
        android:id="@+id/tabText"/>
      </RelativeLayout>
    

    createTab becomes:

      private RelativeLayout createTab(String titleText, int tabBackgroundDrawableId)
    {
        RelativeLayout rl = (RelativeLayout)this.getLayoutInflater().inflate(R.layout.mytab, null, false);  
         //set appearance of tab
        rl.setBackgroundResource(tabBackgroundDrawableId);
    
        TextView tv = (TextView)rl.findViewById(R.id.tabText);
        //set caption       
        tv.setText(titleText);     
    
        ImageView iv = (ImageView)rl.findViewById(R.id.tabIcon);
    
        iv.setImageResource(R.drawable.ic_launcher);//or supply unique drawable to method?      
        return rl;      
    }