diff options
author | Jack Veenstra <veenstra@android.com> | 2009-06-01 21:27:01 -0700 |
---|---|---|
committer | Jack Veenstra <veenstra@android.com> | 2009-06-10 11:38:02 -0700 |
commit | 53175148c9b962c0ffe9cea0f3dc68bc0196e044 (patch) | |
tree | 169762ef55c30a9e5ccfa929c45c087c3cf51871 /core/java/android | |
parent | a32b5f3252a58416f328399680395aa5fa936640 (diff) | |
download | frameworks_base-53175148c9b962c0ffe9cea0f3dc68bc0196e044.zip frameworks_base-53175148c9b962c0ffe9cea0f3dc68bc0196e044.tar.gz frameworks_base-53175148c9b962c0ffe9cea0f3dc68bc0196e044.tar.bz2 |
Add support for custom tab views in TabHost and TabWidget.
This change adds the ability to specify an arbitrary view for a tab
indicator. It also adds support for specifying a drawable to use as
the divider between tab views.
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/widget/TabHost.java | 38 | ||||
-rw-r--r-- | core/java/android/widget/TabWidget.java | 110 |
2 files changed, 128 insertions, 20 deletions
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java index 5bf8035..103d44d 100644 --- a/core/java/android/widget/TabHost.java +++ b/core/java/android/widget/TabHost.java @@ -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; } @@ -411,6 +417,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } /** + * 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; } } @@ -526,6 +540,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. */ private class ViewIdContentStrategy implements ContentStrategy { diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 20cddcb..a26bfa2 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -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; |