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