PagerTabStrip.java revision 24cc55cb5775a71ff144a3588003fa8e52951c7d
124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell/* 224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * Copyright (C) 2012 The Android Open Source Project 324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * you may not use this file except in compliance with the License. 624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * You may obtain a copy of the License at 724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 1024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * Unless required by applicable law or agreed to in writing, software 1124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 1224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * See the License for the specific language governing permissions and 1424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * limitations under the License. 1524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell */ 1624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 1724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellpackage android.support.v4.view; 1824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 1924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellimport android.content.Context; 2024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellimport android.graphics.Canvas; 2124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellimport android.graphics.Paint; 2224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellimport android.graphics.Rect; 2324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellimport android.util.AttributeSet; 2424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellimport android.view.View; 2524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 2624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell/** 2724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * PagerTabStrip is an interactive indicator of the current, next, 2824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * and previous pages of a {@link ViewPager}. It is intended to be used as a 2924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * child view of a ViewPager widget in your XML layout. 3024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * Add it as a child of a ViewPager in your layout file and set its 3124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom 3224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * of the ViewPager. The title from each page is supplied by the method 3324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * {@link PagerAdapter#getPageTitle(int)} in the adapter supplied to 3424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * the ViewPager. 3524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 3624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * <p>For a non-interactive indicator, see {@link PagerTitleStrip}.</p> 3724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell */ 3824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powellpublic class PagerTabStrip extends PagerTitleStrip { 3924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private static final int INDICATOR_HEIGHT = 3; // dp 4024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private static final int MIN_PADDING_BOTTOM = INDICATOR_HEIGHT + 3; // dp 4124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private static final int TAB_PADDING = 16; // dp 4224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private static final int TAB_SPACING = 32; // dp 4324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private static final int MIN_TEXT_SPACING = TAB_SPACING + TAB_PADDING * 2; // dp 4424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 4524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private int mIndicatorColor; 4624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private int mIndicatorHeight; 4724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 4824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private int mMinPaddingBottom; 4924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private int mMinTextSpacing; 5024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 5124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private int mTabPadding; 5224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 5324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private final Paint mTabPaint = new Paint(); 5424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private final Rect mTempRect = new Rect(); 5524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 5624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell private int mTabAlpha = 0xFF; 5724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 5824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public PagerTabStrip(Context context) { 5924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell this(context, null); 6024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 6124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 6224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public PagerTabStrip(Context context, AttributeSet attrs) { 6324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell super(context, attrs); 6424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 6524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mIndicatorColor = mTextColor; 6624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mTabPaint.setColor(mIndicatorColor); 6724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 6824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell // Note: this follows the rules for Resources#getDimensionPixelOffset/Size: 6924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell // sizes round up, offsets round down. 7024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell final float density = context.getResources().getDisplayMetrics().density; 7124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mIndicatorHeight = (int) (INDICATOR_HEIGHT * density + 0.5f); 7224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mMinPaddingBottom = (int) (MIN_PADDING_BOTTOM * density + 0.5f); 7324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mMinTextSpacing = (int) (MIN_TEXT_SPACING * density); 7424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mTabPadding = (int) (TAB_PADDING * density + 0.5f); 7524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 7624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell // Enforce restrictions 7724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()); 7824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell setTextSpacing(getTextSpacing()); 7924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 8024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell setWillNotDraw(false); 8124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 8224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mPrevText.setFocusable(true); 8324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mPrevText.setOnClickListener(new OnClickListener() { 8424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell @Override 8524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public void onClick(View v) { 8624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mPager.setCurrentItem(mPager.getCurrentItem() - 1); 8724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 8824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell }); 8924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 9024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mNextText.setFocusable(true); 9124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mNextText.setOnClickListener(new OnClickListener() { 9224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell @Override 9324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public void onClick(View v) { 9424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mPager.setCurrentItem(mPager.getCurrentItem() + 1); 9524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 9624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell }); 9724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 9824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 9924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell /** 10024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * Set the color of the tab indicator bar. 10124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 10224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * @param color Color to set as an 0xRRGGBB value. The high byte (alpha) is ignored. 10324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell */ 10424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public void setTabIndicatorColor(int color) { 10524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mIndicatorColor = color; 10624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mTabPaint.setColor(mIndicatorColor); 10724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell invalidate(); 10824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 10924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 11024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell /** 11124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * Set the color of the tab indicator bar from a color resource. 11224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 11324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * @param resId Resource ID of a color resource to load 11424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell */ 11524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public void setTabIndicatorColorResource(int resId) { 11624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell setTabIndicatorColor(getContext().getResources().getColor(resId)); 11724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 11824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 11924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell /** 12024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * @return The current tab indicator color as an 0xRRGGBB value. 12124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell */ 12224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public int getTabIndicatorColor() { 12324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell return mIndicatorColor; 12424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 12524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 12624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell @Override 12724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public void setPadding(int left, int top, int right, int bottom) { 12824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell if (bottom < mMinPaddingBottom) { 12924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell bottom = mMinPaddingBottom; 13024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 13124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell super.setPadding(left, top, right, bottom); 13224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 13324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 13424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell @Override 13524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public void setTextSpacing(int textSpacing) { 13624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell if (textSpacing < mMinTextSpacing) { 13724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell textSpacing = mMinTextSpacing; 13824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 13924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell super.setTextSpacing(textSpacing); 14024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 14124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 14224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell @Override 14324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell protected void onDraw(Canvas canvas) { 14424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell super.onDraw(canvas); 14524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 14624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell final int bottom = getHeight(); 14724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell final int left = mCurrText.getLeft() - mTabPadding; 14824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell final int right = mCurrText.getRight() + mTabPadding; 14924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell final int top = bottom - mIndicatorHeight; 15024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 15124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mTabPaint.setColor(mTabAlpha << 24 | (mIndicatorColor & 0xFFFFFF)); 15224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell canvas.drawRect(left, top, right, bottom, mTabPaint); 15324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 15424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 15524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell @Override 15624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell void updateTextPositions(int position, float positionOffset, boolean force) { 15724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell final Rect r = mTempRect; 15824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell int bottom = getHeight(); 15924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell int left = mCurrText.getLeft() - mTabPadding; 16024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell int right = mCurrText.getRight() + mTabPadding; 16124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell int top = bottom - mIndicatorHeight; 16224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 16324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell r.set(left, top, right, bottom); 16424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 16524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell super.updateTextPositions(position, positionOffset, force); 16624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell mTabAlpha = (int) (Math.abs(positionOffset - 0.5f) * 2 * 0xFF); 16724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 16824cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell left = mCurrText.getLeft() - mTabPadding; 16924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell right = mCurrText.getRight() + mTabPadding; 17024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell r.union(left, top, right, bottom); 17124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 17224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell invalidate(r); 17324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 17424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell} 175