Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: customizing the look of Tabs using TabHost & TabWidget

I opend a post about this before but I feel that I can now (after reading some other posts) better explain what I want and rephrase it so it will be better understand.

I followed the tutorial about Tab Layout on the dev guide and I managed to create tabs with it, but I want to do some customization to it (and I did look on other posts, but either the code had many mistakes to it or it didn't answer what I'm looking for).

  1. The first problem I have is that the test is in most part over the icon instead of below it (I used an icon with dimensions 48x48 as recommended on the dev guide). I want the tab with to act like wrap_content does. I also want to change the text size (I think it's called the label).

  2. I want to use hex triplets to change the background color of the tabs, to change it between to situations : when this tab is the one selected and when it's not.

  3. I want to be able to change the color of the line that is below the tabs, I could not find any information on how to do this.

The code I'm currently using to create a new tab is (from the dev guide):

    intent = new Intent().setClass(this, GroupsActivity.class);
    spec = tabHost.newTabSpec("groups").setIndicator("groups",
                      res.getDrawable(R.drawable.ic_tab_groups))
                  .setContent(intent);
    tabHost.addTab(spec);

(groups is the tab name).

Help is very much appreciated!

like image 762
Belgi Avatar asked Oct 16 '11 13:10

Belgi


3 Answers

Rather than trying to customize the widget tabs themselves, here is an alternate approach that I've used successfully on a project that may save you some headaches:

The idea is to use a hidden TabWidget in your layout and control it with a customized LinearLayout containing Buttons. This way, you can more easily customize the buttons to look however you'd like. You'll control the actual TabWidget in your Activity within each button's OnClick.

  1. Create your layout with both the TabWidget and the Buttons:

        <?xml version="1.0" encoding="utf-8"?>
    <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/tabhost" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <RelativeLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:gravity="bottom">
            <TabWidget android:id="@android:id/tabs"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:visibility="gone" />
    
            <LinearLayout android:id="@+id/tabbar"
                android:orientation="horizontal" android:layout_width="fill_parent"
                android:layout_height="wrap_content">
                <Button android:id="@+id/firstButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_first_on"
                    android:layout_width="100dp" android:layout_height="43dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/secondButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_second_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/thirdButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_third_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
                <Button android:id="@+id/forthButton"
                    android:layout_alignParentTop="true" android:background="@drawable/btn_forth_off"
                    android:layout_height="43dp" android:layout_width="100dp"
                    android:clickable="true"></Button>
            </LinearLayout>
    
            <FrameLayout android:id="@android:id/tabcontent"
                android:layout_width="fill_parent" android:layout_height="fill_parent"
                android:layout_below="@+id/tabbar" />
    
        </RelativeLayout>
    </TabHost>
    
  2. Set up the onCreate of your activity to handle using the buttons for adjusting the tab views:

        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            // tabs        
            firstButton = (Button) findViewById(R.id.firstButton);
            secondButton = (Button) findViewById(R.id.secondButton);        
            thirdButton = (Button) findViewById(R.id.thirdButton);
            forthButton = (Button) findViewById(R.id.forthButton);
    
            Resources res = getResources(); // Resource object to get Drawables
            final TabHost tabHost = getTabHost();  // The activity TabHost
            TabHost.TabSpec spec;  // Resusable TabSpec for each tab
            Intent intent;  // Reusable Intent for each tab
    
            intent = new Intent().setClass(this, FirstGroupActivity.class);
            spec = tabHost.newTabSpec("first").setIndicator("First").setContent(intent);
            tabHost.addTab(spec);
            intent = new Intent().setClass(this, SecondGroupActivity.class);
            spec = tabHost.newTabSpec("second").setIndicator("Second").setContent(intent);
            tabHost.addTab(spec);   
    
            intent = new Intent().setClass(this, ThirdGroupActivity.class);
            spec = tabHost.newTabSpec("third").setIndicator("Third").setContent(intent);
            tabHost.addTab(spec);
    
    
            intent = new Intent().setClass(this, ForthActivity.class);
            spec = tabHost.newTabSpec("forth").setIndicator("Forth").setContent(intent);
            tabHost.addTab(spec);
    
    
            tabHost.setCurrentTab(0);
    
            firstButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(0);
                    firstButton.setBackgroundResource(R.drawable.btn_first_on);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);            
                }
    
            });
    
    
            secondButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(1);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_on);                       
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);                        
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);
    
                }
    
            });
    
    
            thirdButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(3);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_on);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_off);
    
                }
    
            });
    
    
            forthButton.setOnClickListener(new OnClickListener() {
    
                public void onClick(View v)
                {
                    tabHost.setCurrentTab(4);
                    firstButton.setBackgroundResource(R.drawable.btn_first_off);
                    secondButton.setBackgroundResource(R.drawable.btn_second_off);              
                    thirdButton.setBackgroundResource(R.drawable.btn_third_off);
                    forthButton.setBackgroundResource(R.drawable.btn_forth_on);
    
                }
    
            });
        }
    

As you can see, I'm using drawables for the images of the buttons on and off. Using this technique, you're not limited to the options available when simply just trying to customize the look of the TabWidget's tabs and you can create a completely custom look to your tabs.

like image 137
SBerg413 Avatar answered Nov 12 '22 01:11

SBerg413


1- Use a custom view:

    spec = tabHost.newTabSpec("groups");
    View view = LayoutInflater.from(this).inflate(R.layout.tabwidget_tabs, tabHost.getTabWidget(), false);
    spec.setIndicator(view);
    spec.setContent(intent);

instead of:

    spec = tabHost.newTabSpec("groups").setIndicator("groups", res.getDrawable(R.drawable.ic_tab_groups)).setContent(intent);
    tabHost.addTab(spec);

And then define the view for the tabs in the file tabwidget_tabs.xml (you can define an ImageView before the textView and the textsize):

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tabsLayout" 
        android:layout_width="wrap_content"
        android:layout_height="34dp"
        android:background="@drawable/tabs_bkgrd"
        android:padding="5dp" 
        android:orientation="vertical">

        <TextView android:id="@+id/tabsText" 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:singleLine="true"
            android:textStyle="bold" 
            android:gravity="center_horizontal"
            android:textSize="14dp" />
    </LinearLayout>

2- It's not possible to use hex triplets to change the background color of the tabs because are drawables not colors. However you can use a selector that changes the drawables. and you can combine this solution with setColorFilter() and android:tint and then you can select the background using hex triplets: How to tint a bitmap

tabs_bkgrd.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <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="@drawable/tab_unselected_shape" />
    <item android:state_focused="false" android:state_selected="true" 
        android:state_pressed="false" android:drawable="@drawable/tab_selected_shape" /> 

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

    <!-- Pressed -->
    <item android:state_pressed="true" android:drawable="@drawable/tab_pressed_shape" /> 

    </selector>

You can define a color or a shape, tab_selected_shape.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
                android:shape="rectangle">
            <gradient android:startColor="@color/gold1"
                android:centerColor="@color/gold2" 
                android:endColor="@color/gold2"
                android:angle="@integer/vertical_shape" />
    </shape>

3- The line is a drawable too. you can find the files in the sdk and copy them into your project after modify them to change the color using gimp. You can combine this solution with setColorFilter() and android:tint and then you can select the background using hex triplets too. Read: further explanation

android-sdk-linux_x86/platforms/android-7/data/res/drawable

tab_bottom_left.xml,  
tab_bottom_right.xml,  
tab_indicator.xml  (define state changes)

android-sdk-linux_x86/platforms/android-7/data/res/drawable-mdpi

tab_focus.9.png (change color)
tab_focus_bar_left.9.png
tab_focus_bar_right.9.png
tab_press.9.png (change color)
tab_press_bar_left.9.png
tab_press_bar_right.9.png
tab_selected.9.png (change color)
tab_selected_bar_left.9.png tab_selected_bar_right.9.png
tab_unselected.9.png

like image 40
albodelu Avatar answered Nov 12 '22 03:11

albodelu


What about the solution I proposed on this question?

You can customize the drawable of each button using the same used by native Android Tab bar(looking for resources in Android.jar to find the right drawables), plus you can customize additional behavious as you desire.

At the end, you will obtain something that is graphically similar to a tabbar, from an user perspective, but acts differently from a developer perspective.

like image 20
Rainbowbreeze Avatar answered Nov 12 '22 01:11

Rainbowbreeze