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/widget | |
| 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/widget')
| -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; | 
