PagerTabStrip.java revision 24cc55cb5775a71ff144a3588003fa8e52951c7d
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.view; 18 19import android.content.Context; 20import android.graphics.Canvas; 21import android.graphics.Paint; 22import android.graphics.Rect; 23import android.util.AttributeSet; 24import android.view.View; 25 26/** 27 * PagerTabStrip is an interactive indicator of the current, next, 28 * and previous pages of a {@link ViewPager}. It is intended to be used as a 29 * child view of a ViewPager widget in your XML layout. 30 * Add it as a child of a ViewPager in your layout file and set its 31 * android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom 32 * of the ViewPager. The title from each page is supplied by the method 33 * {@link PagerAdapter#getPageTitle(int)} in the adapter supplied to 34 * the ViewPager. 35 * 36 * <p>For a non-interactive indicator, see {@link PagerTitleStrip}.</p> 37 */ 38public class PagerTabStrip extends PagerTitleStrip { 39 private static final int INDICATOR_HEIGHT = 3; // dp 40 private static final int MIN_PADDING_BOTTOM = INDICATOR_HEIGHT + 3; // dp 41 private static final int TAB_PADDING = 16; // dp 42 private static final int TAB_SPACING = 32; // dp 43 private static final int MIN_TEXT_SPACING = TAB_SPACING + TAB_PADDING * 2; // dp 44 45 private int mIndicatorColor; 46 private int mIndicatorHeight; 47 48 private int mMinPaddingBottom; 49 private int mMinTextSpacing; 50 51 private int mTabPadding; 52 53 private final Paint mTabPaint = new Paint(); 54 private final Rect mTempRect = new Rect(); 55 56 private int mTabAlpha = 0xFF; 57 58 public PagerTabStrip(Context context) { 59 this(context, null); 60 } 61 62 public PagerTabStrip(Context context, AttributeSet attrs) { 63 super(context, attrs); 64 65 mIndicatorColor = mTextColor; 66 mTabPaint.setColor(mIndicatorColor); 67 68 // Note: this follows the rules for Resources#getDimensionPixelOffset/Size: 69 // sizes round up, offsets round down. 70 final float density = context.getResources().getDisplayMetrics().density; 71 mIndicatorHeight = (int) (INDICATOR_HEIGHT * density + 0.5f); 72 mMinPaddingBottom = (int) (MIN_PADDING_BOTTOM * density + 0.5f); 73 mMinTextSpacing = (int) (MIN_TEXT_SPACING * density); 74 mTabPadding = (int) (TAB_PADDING * density + 0.5f); 75 76 // Enforce restrictions 77 setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()); 78 setTextSpacing(getTextSpacing()); 79 80 setWillNotDraw(false); 81 82 mPrevText.setFocusable(true); 83 mPrevText.setOnClickListener(new OnClickListener() { 84 @Override 85 public void onClick(View v) { 86 mPager.setCurrentItem(mPager.getCurrentItem() - 1); 87 } 88 }); 89 90 mNextText.setFocusable(true); 91 mNextText.setOnClickListener(new OnClickListener() { 92 @Override 93 public void onClick(View v) { 94 mPager.setCurrentItem(mPager.getCurrentItem() + 1); 95 } 96 }); 97 } 98 99 /** 100 * Set the color of the tab indicator bar. 101 * 102 * @param color Color to set as an 0xRRGGBB value. The high byte (alpha) is ignored. 103 */ 104 public void setTabIndicatorColor(int color) { 105 mIndicatorColor = color; 106 mTabPaint.setColor(mIndicatorColor); 107 invalidate(); 108 } 109 110 /** 111 * Set the color of the tab indicator bar from a color resource. 112 * 113 * @param resId Resource ID of a color resource to load 114 */ 115 public void setTabIndicatorColorResource(int resId) { 116 setTabIndicatorColor(getContext().getResources().getColor(resId)); 117 } 118 119 /** 120 * @return The current tab indicator color as an 0xRRGGBB value. 121 */ 122 public int getTabIndicatorColor() { 123 return mIndicatorColor; 124 } 125 126 @Override 127 public void setPadding(int left, int top, int right, int bottom) { 128 if (bottom < mMinPaddingBottom) { 129 bottom = mMinPaddingBottom; 130 } 131 super.setPadding(left, top, right, bottom); 132 } 133 134 @Override 135 public void setTextSpacing(int textSpacing) { 136 if (textSpacing < mMinTextSpacing) { 137 textSpacing = mMinTextSpacing; 138 } 139 super.setTextSpacing(textSpacing); 140 } 141 142 @Override 143 protected void onDraw(Canvas canvas) { 144 super.onDraw(canvas); 145 146 final int bottom = getHeight(); 147 final int left = mCurrText.getLeft() - mTabPadding; 148 final int right = mCurrText.getRight() + mTabPadding; 149 final int top = bottom - mIndicatorHeight; 150 151 mTabPaint.setColor(mTabAlpha << 24 | (mIndicatorColor & 0xFFFFFF)); 152 canvas.drawRect(left, top, right, bottom, mTabPaint); 153 } 154 155 @Override 156 void updateTextPositions(int position, float positionOffset, boolean force) { 157 final Rect r = mTempRect; 158 int bottom = getHeight(); 159 int left = mCurrText.getLeft() - mTabPadding; 160 int right = mCurrText.getRight() + mTabPadding; 161 int top = bottom - mIndicatorHeight; 162 163 r.set(left, top, right, bottom); 164 165 super.updateTextPositions(position, positionOffset, force); 166 mTabAlpha = (int) (Math.abs(positionOffset - 0.5f) * 2 * 0xFF); 167 168 left = mCurrText.getLeft() - mTabPadding; 169 right = mCurrText.getRight() + mTabPadding; 170 r.union(left, top, right, bottom); 171 172 invalidate(r); 173 } 174} 175