Merge change 2900 into donut

* changes:
  Add support for custom tab views in TabHost and TabWidget.
This commit is contained in:
Android (Google) Code Review
2009-06-10 11:41:49 -07:00
3 changed files with 203 additions and 21 deletions

View File

@@ -46362,7 +46362,7 @@
</parameter>
<parameter name="height" type="int">
</parameter>
<parameter name="edge" type="int">
<parameter name="inset" type="int">
</parameter>
<parameter name="color" type="int">
</parameter>
@@ -173571,6 +173571,17 @@
deprecated="not deprecated"
visibility="public"
>
<method name="getTag"
return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="setContent"
return="android.widget.TabHost.TabSpec"
abstract="false"
@@ -173638,6 +173649,19 @@
<parameter name="icon" type="android.graphics.drawable.Drawable">
</parameter>
</method>
<method name="setIndicator"
return="android.widget.TabHost.TabSpec"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="view" type="android.view.View">
</parameter>
</method>
</class>
<class name="TabWidget"
extends="android.widget.LinearLayout"
@@ -173711,6 +173735,30 @@
<parameter name="index" type="int">
</parameter>
</method>
<method name="getChildTabViewAt"
return="android.view.View"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="index" type="int">
</parameter>
</method>
<method name="getTabCount"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="onFocusChange"
return="void"
abstract="false"
@@ -173739,6 +173787,32 @@
<parameter name="index" type="int">
</parameter>
</method>
<method name="setDividerDrawable"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="drawable" type="android.graphics.drawable.Drawable">
</parameter>
</method>
<method name="setDividerDrawable"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="resId" type="int">
</parameter>
</method>
</class>
<class name="TableLayout"
extends="android.widget.LinearLayout"

View File

@@ -177,7 +177,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
// leaving touch mode.. if nothing has focus, let's give it to
// the indicator of the current tab
if (!mCurrentView.hasFocus() || mCurrentView.isFocused()) {
mTabWidget.getChildAt(mCurrentTab).requestFocus();
mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
}
}
}
@@ -197,6 +197,12 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
}
View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();
tabIndicator.setOnKeyListener(mTabKeyListener);
// If this is a custom view, then do not draw the bottom strips for
// the tab indicators.
if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) {
mTabWidget.setDrawBottomStrips(false);
}
mTabWidget.addView(tabIndicator);
mTabSpecs.add(tabSpec);
@@ -235,7 +241,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
public View getCurrentTabView() {
if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
return mTabWidget.getChildAt(mCurrentTab);
return mTabWidget.getChildTabViewAt(mCurrentTab);
}
return null;
}
@@ -273,7 +279,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
&& (mCurrentView.isRootNamespace())
&& (mCurrentView.hasFocus())
&& (mCurrentView.findFocus().focusSearch(View.FOCUS_UP) == null)) {
mTabWidget.getChildAt(mCurrentTab).requestFocus();
mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
return true;
}
@@ -410,6 +416,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
return this;
}
/**
* Specify a view as the tab indicator.
*/
public TabSpec setIndicator(View view) {
mIndicatorStrategy = new ViewIndicatorStrategy(view);
return this;
}
/**
* Specify the id of the view that should be used as the content
* of the tab.
@@ -437,7 +451,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
}
String getTag() {
public String getTag() {
return mTag;
}
}
@@ -525,6 +539,22 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
}
}
/**
* How to create a tab indicator by specifying a view.
*/
private class ViewIndicatorStrategy implements IndicatorStrategy {
private final View mView;
private ViewIndicatorStrategy(View view) {
mView = view;
}
public View createIndicatorView() {
return mView;
}
}
/**
* How to create the tab content via a view id.
*/

View File

@@ -49,6 +49,8 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
private Drawable mBottomLeftStrip;
private Drawable mBottomRightStrip;
private boolean mStripMoved;
private Drawable mDividerDrawable;
private boolean mDrawBottomStrips = true;
public TabWidget(Context context) {
this(context, null);
@@ -87,9 +89,68 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
setOnFocusChangeListener(this);
}
/**
* Returns the tab indicator view at the given index.
*
* @param index the zero-based index of the tab indicator view to return
* @return the tab indicator view at the given index
*/
public View getChildTabViewAt(int index) {
// If we are using dividers, then instead of tab views at 0, 1, 2, ...
// we have tab views at 0, 2, 4, ...
if (mDividerDrawable != null) {
index *= 2;
}
return getChildAt(index);
}
/**
* Returns the number of tab indicator views.
* @return the number of tab indicator views.
*/
public int getTabCount() {
int children = getChildCount();
// If we have dividers, then we will always have an odd number of
// children: 1, 3, 5, ... and we want to convert that sequence to
// this: 1, 2, 3, ...
if (mDividerDrawable != null) {
children = (children + 1) / 2;
}
return children;
}
/**
* Sets the drawable to use as a divider between the tab indicators.
* @param drawable the divider drawable
*/
public void setDividerDrawable(Drawable drawable) {
mDividerDrawable = drawable;
}
/**
* Sets the drawable to use as a divider between the tab indicators.
* @param resId the resource identifier of the drawable to use as a
* divider.
*/
public void setDividerDrawable(int resId) {
mDividerDrawable = mContext.getResources().getDrawable(resId);
}
/**
* Controls whether the bottom strips on the tab indicators are drawn or
* not. The default is to draw them. If the user specifies a custom
* view for the tab indicators, then the TabHost class calls this method
* to disable drawing of the bottom strips.
* @param drawBottomStrips true if the bottom strips should be drawn.
*/
void setDrawBottomStrips(boolean drawBottomStrips) {
mDrawBottomStrips = drawBottomStrips;
}
@Override
public void childDrawableStateChanged(View child) {
if (child == getChildAt(mSelectedTab)) {
if (child == getChildTabViewAt(mSelectedTab)) {
// To make sure that the bottom strip is redrawn
invalidate();
}
@@ -100,7 +161,14 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
View selectedChild = getChildAt(mSelectedTab);
// If the user specified a custom view for the tab indicators, then
// do not draw the bottom strips.
if (!mDrawBottomStrips) {
// Skip drawing the bottom strips.
return;
}
View selectedChild = getChildTabViewAt(mSelectedTab);
mBottomLeftStrip.setState(selectedChild.getDrawableState());
mBottomRightStrip.setState(selectedChild.getDrawableState());
@@ -157,13 +225,13 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
* @see #focusCurrentTab
*/
public void setCurrentTab(int index) {
if (index < 0 || index >= getChildCount()) {
if (index < 0 || index >= getTabCount()) {
return;
}
getChildAt(mSelectedTab).setSelected(false);
getChildTabViewAt(mSelectedTab).setSelected(false);
mSelectedTab = index;
getChildAt(mSelectedTab).setSelected(true);
getChildTabViewAt(mSelectedTab).setSelected(true);
mStripMoved = true;
}
@@ -189,17 +257,17 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
// change the focus if applicable.
if (oldTab != index) {
getChildAt(index).requestFocus();
getChildTabViewAt(index).requestFocus();
}
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
int count = getChildCount();
int count = getTabCount();
for (int i=0; i<count; i++) {
View child = getChildAt(i);
for (int i = 0; i < count; i++) {
View child = getChildTabViewAt(i);
child.setEnabled(enabled);
}
}
@@ -218,17 +286,26 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
child.setFocusable(true);
child.setClickable(true);
// If we have dividers between the tabs and we already have at least one
// tab, then add a divider before adding the next tab.
if (mDividerDrawable != null && getTabCount() > 0) {
View divider = new View(mContext);
final LinearLayout.LayoutParams lp = new LayoutParams(
mDividerDrawable.getIntrinsicWidth(),
mDividerDrawable.getIntrinsicHeight());
lp.setMargins(0, 0, 0, 0);
divider.setLayoutParams(lp);
divider.setBackgroundDrawable(mDividerDrawable);
super.addView(divider);
}
super.addView(child);
// TODO: detect this via geometry with a tabwidget listener rather
// than potentially interfere with the view's listener
child.setOnClickListener(new TabClickListener(getChildCount() - 1));
child.setOnClickListener(new TabClickListener(getTabCount() - 1));
child.setOnFocusChangeListener(this);
}
/**
* Provides a way for {@link TabHost} to be notified that the user clicked on a tab indicator.
*/
@@ -238,14 +315,15 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
public void onFocusChange(View v, boolean hasFocus) {
if (v == this && hasFocus) {
getChildAt(mSelectedTab).requestFocus();
getChildTabViewAt(mSelectedTab).requestFocus();
return;
}
if (hasFocus) {
int i = 0;
while (i < getChildCount()) {
if (getChildAt(i) == v) {
int numTabs = getTabCount();
while (i < numTabs) {
if (getChildTabViewAt(i) == v) {
setCurrentTab(i);
mSelectionChangedListener.onTabSelectionChanged(i, false);
break;