I've run into a situation where the TabWidget layout didn't do what I needed, so I faked it up with a ViewFlipper and a RadioGroup. That way, I could define the content of the tabs (each view in the ViewFlipper) using includes (like in Farray's answer).
The tabs themselves were the RadioButtons in the RadioGroup - you just have an OnCheckedChangeListener in your code and set the ViewFlipper's displayed child accordingly. You can define the RadioButton layout in XML (with text or images or whatever).
Here's a pseudo-layout where the tabs use images:
<LinearLayout>
<ViewFlipper android:id="@+id/viewFlipper">
<include android:id="@+id/tab1Content" layout="@layout/tab1Layout" />
<include android:id="@+id/tab2Content" layout="@layout/tab2Layout" />
<include android:id="@+id/tab3Content" layout="@layout/tab3Layout" />
</ViewFlipper>
<LinearLayout>
<RadioGroup android:id="@+id/radgroup1" android:orientation="horizontal">
<RadioButton android:id="@+id/rad1" android:button="@drawable/tab1" />
<RadioButton android:id="@+id/rad2" android:button="@drawable/tab2" />
<RadioButton android:id="@+id/rad3" android:button="@drawable/tab3" />
</RadioGroup>
</LinearLayout>
</LinearLayout>
And here's the listener:
private OnCheckedChangeListener onRadioButtonCheckedChanged = new OnCheckedChangeListener(){
public void onCheckedChanged(RadioGroup group, int checkedId)
{
switch(checkedId)
{
case(R.id.rad2):
viewFlipper.setDisplayedChild(1);
break;
case(R.id.rad3):
viewFlipper.setDisplayedChild(2);
break;
default:
viewFlipper.setDisplayedChild(0);
break;
}
}
};