Android Open Source - mvfa Tab Widget






From Project

Back to project page mvfa.

License

The source code is released under:

GNU General Public License

If you think the Android project mvfa listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2006 The Android Open Source Project
 */*from  w ww . j a va2s . c o m*/
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package my.android.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import be.benvd.mvforandroid.R;

/**
 * 
 * Displays a list of tab labels representing each page in the parent's tab
 * collection. The container object for this widget is
 * {@link my.android.widget.TabHost TabHost}. When the user selects a tab, this
 * object sends a message to the parent container, TabHost, to tell it to switch
 * the displayed page. You typically won't use many methods directly on this
 * object. The container TabHost is used to add labels, add the callback
 * handler, and manage callbacks. You might call this object to iterate the list
 * of tabs, or to tweak the layout of the tab list, but most methods should be
 * called on the containing TabHost object.
 */
public class TabWidget extends LinearLayout implements OnFocusChangeListener
  {

  Context mContext;

  private OnTabSelectionChanged mSelectionChangedListener;
  private int mSelectedTab = 0;
  private Drawable mBottomLeftStrip;
  private Drawable mBottomRightStrip;
  private boolean mStripMoved;
  private Drawable mDividerDrawable;
  private boolean mDrawBottomStrips = true;

  public TabWidget(Context context)
    {
    this(context, null);
    mContext = context;
    }

  public TabWidget(Context context, AttributeSet attrs)
    {
    this(context, attrs, android.R.attr.tabWidgetStyle);
    mContext = context;
    }

  public TabWidget(Context context, AttributeSet attrs, int defStyle)
    {
    super(context, attrs);
    mContext = context;
    initTabWidget();

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabWidget, defStyle, 0);

    a.recycle();

    }

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
    mStripMoved = true;
    super.onSizeChanged(w, h, oldw, oldh);
    }

  private void initTabWidget()
    {
    setOrientation(LinearLayout.HORIZONTAL);
    mBottomLeftStrip = mContext.getResources().getDrawable(R.drawable.tab_bottom_left);
    mBottomRightStrip = mContext.getResources().getDrawable(R.drawable.tab_bottom_right);
    // Deal with focus, as we don't want the focus to go by default
    // to a tab other than the current tab
    setFocusable(true);
    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 == getChildTabViewAt(mSelectedTab))
      {
      // To make sure that the bottom strip is redrawn
      invalidate();
      }
    super.childDrawableStateChanged(child);
    }

  @Override
  public void dispatchDraw(Canvas canvas)
    {
    super.dispatchDraw(canvas);

    // 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());

    if(mStripMoved)
      {
      Rect selBounds = new Rect(); // Bounds of the selected tab indicator
      selBounds.left = selectedChild.getLeft();
      selBounds.right = selectedChild.getRight();
      final int myHeight = getHeight();
      mBottomLeftStrip.setBounds(Math.min(0, selBounds.left - mBottomLeftStrip.getIntrinsicWidth()), myHeight - mBottomLeftStrip.getIntrinsicHeight(),
          selBounds.left, getHeight());
      mBottomRightStrip.setBounds(selBounds.right, myHeight - mBottomRightStrip.getIntrinsicHeight(),
          Math.max(getWidth(), selBounds.right + mBottomRightStrip.getIntrinsicWidth()), myHeight);
      mStripMoved = false;
      }

    mBottomLeftStrip.draw(canvas);
    mBottomRightStrip.draw(canvas);
    }

  /**
   * Sets the current tab. This method is used to bring a tab to the front of
   * the Widget, and is used to post to the rest of the UI that a different
   * tab has been brought to the foreground.
   * 
   * Note, this is separate from the traditional "focus" that is employed from
   * the view logic.
   * 
   * For instance, if we have a list in a tabbed view, a user may be
   * navigating up and down the list, moving the UI focus (orange
   * highlighting) through the list items. The cursor movement does not effect
   * the "selected" tab though, because what is being scrolled through is all
   * on the same tab. The selected tab only changes when we navigate between
   * tabs (moving from the list view to the next tabbed view, in this
   * example).
   * 
   * To move both the focus AND the selected tab at once, please use
   * {@link #setCurrentTab}. Normally, the view logic takes care of adjusting
   * the focus, so unless you're circumventing the UI, you'll probably just
   * focus your interest here.
   * 
   * @param index
   *            The tab that you want to indicate as the selected tab (tab
   *            brought to the front of the widget)
   * 
   * @see #focusCurrentTab
   */
  public void setCurrentTab(int index)
    {
    if(index < 0 || index >= getTabCount())
      {
      return;
      }

    getChildTabViewAt(mSelectedTab).setSelected(false);
    mSelectedTab = index;
    getChildTabViewAt(mSelectedTab).setSelected(true);
    mStripMoved = true;
    }

  /**
   * Sets the current tab and focuses the UI on it. This method makes sure
   * that the focused tab matches the selected tab, normally at
   * {@link #setCurrentTab}. Normally this would not be an issue if we go
   * through the UI, since the UI is responsible for calling
   * TabWidget.onFocusChanged(), but in the case where we are selecting the
   * tab programmatically, we'll need to make sure focus keeps up.
   * 
   * @param index
   *            The tab that you want focused (highlighted in orange) and
   *            selected (tab brought to the front of the widget)
   * 
   * @see #setCurrentTab
   */
  public void focusCurrentTab(int index)
    {
    final int oldTab = mSelectedTab;

    // set the tab
    setCurrentTab(index);

    // change the focus if applicable.
    if(oldTab != index)
      {
      getChildTabViewAt(index).requestFocus();
      }
    }

  @Override
  public void setEnabled(boolean enabled)
    {
    super.setEnabled(enabled);
    int count = getTabCount();

    for(int i = 0; i < count; i++)
      {
      View child = getChildTabViewAt(i);
      child.setEnabled(enabled);
      }
    }

  @Override
  public void addView(View child)
    {
    if(child.getLayoutParams() == null)
      {
      final LinearLayout.LayoutParams lp = new LayoutParams(0, ViewGroup.LayoutParams.FILL_PARENT, 1.0f);
      lp.setMargins(0, 0, 0, 0);
      child.setLayoutParams(lp);
      }

    // Ensure you can navigate to the tab with the keyboard, and you can
    // touch it
    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)
      {
      ImageView divider = new ImageView(mContext);
      final LinearLayout.LayoutParams lp = new LayoutParams(mDividerDrawable.getIntrinsicWidth(), LayoutParams.FILL_PARENT);
      lp.setMargins(0, 0, 0, 0);
      divider.setLayoutParams(lp);
      divider.setBackgroundDrawable(mDividerDrawable);
      super.addView(divider);
      }
    super.addView(child);

    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.
   */
  void setTabSelectionListener(OnTabSelectionChanged listener)
    {
    mSelectionChangedListener = listener;
    }

  public void onFocusChange(View v, boolean hasFocus)
    {
    if(v == this && hasFocus)
      {
      getChildTabViewAt(mSelectedTab).requestFocus();
      return;
      }

    if(hasFocus)
      {
      int i = 0;
      int numTabs = getTabCount();
      while(i < numTabs)
        {
        if(getChildTabViewAt(i) == v)
          {
          setCurrentTab(i);
          mSelectionChangedListener.onTabSelectionChanged(i, false);
          break;
          }
        i++;
        }
      }
    }

  // registered with each tab indicator so we can notify tab host
  private class TabClickListener implements OnClickListener
    {

    private final int mTabIndex;

    private TabClickListener(int tabIndex)
      {
      mTabIndex = tabIndex;
      }

    public void onClick(View v)
      {
      mSelectionChangedListener.onTabSelectionChanged(mTabIndex, true);
      }
    }

  /**
   * Let {@link TabHost} know that the user clicked on a tab indicator.
   */
  static interface OnTabSelectionChanged
    {
    /**
     * Informs the TabHost which tab was selected. It also indicates if the
     * tab was clicked/pressed or just focused into.
     * 
     * @param tabIndex
     *            index of the tab that was selected
     * @param clicked
     *            whether the selection changed due to a touch/click or due
     *            to focus entering the tab through navigation. Pass true if
     *            it was due to a press/click and false otherwise.
     */
    void onTabSelectionChanged(int tabIndex, boolean clicked);
    }

  }




Java Source Code List

be.benvd.mvforandroid.CreditActivity.java
be.benvd.mvforandroid.MainActivity.java
be.benvd.mvforandroid.SettingsActivity.java
be.benvd.mvforandroid.TopupsActivity.java
be.benvd.mvforandroid.UsageActivity.java
be.benvd.mvforandroid.data.DatabaseHelper.java
be.benvd.mvforandroid.data.MVDataHelper.java
be.benvd.mvforandroid.data.MVDataService.java
be.benvd.mvforandroid.data.OnAlarmReceiver.java
be.benvd.mvforandroid.data.OnBootReceiver.java
be.benvd.mvforandroid.widgets.WidgetProvider.java
com.commonsware.cwac.merge.MergeAdapter.java
com.commonsware.cwac.sacklist.SackOfViewsAdapter.java
com.commonsware.cwac.wakeful.WakefulIntentService.java
my.android.app.TabActivity.java
my.android.widget.Switcher.java
my.android.widget.TabHost.java
my.android.widget.TabWidget.java