Skip to content

Most visited

Recently visited

navigation
SwipeRefreshMultipleViews / src / com.example.android.common / view /

SlidingTabStrip.java

1
/*
2
 * Copyright (C) 2013 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
 
17
package com.example.android.common.view;
18
 
19
import android.R;
20
import android.content.Context;
21
import android.graphics.Canvas;
22
import android.graphics.Color;
23
import android.graphics.Paint;
24
import android.util.AttributeSet;
25
import android.util.TypedValue;
26
import android.view.View;
27
import android.widget.LinearLayout;
28
 
29
class SlidingTabStrip extends LinearLayout {
30
 
31
    private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2;
32
    private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
33
    private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8;
34
    private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;
35
 
36
    private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1;
37
    private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20;
38
    private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f;
39
 
40
    private final int mBottomBorderThickness;
41
    private final Paint mBottomBorderPaint;
42
 
43
    private final int mSelectedIndicatorThickness;
44
    private final Paint mSelectedIndicatorPaint;
45
 
46
    private final int mDefaultBottomBorderColor;
47
 
48
    private final Paint mDividerPaint;
49
    private final float mDividerHeight;
50
 
51
    private int mSelectedPosition;
52
    private float mSelectionOffset;
53
 
54
    private SlidingTabLayout.TabColorizer mCustomTabColorizer;
55
    private final SimpleTabColorizer mDefaultTabColorizer;
56
 
57
    SlidingTabStrip(Context context) {
58
        this(context, null);
59
    }
60
 
61
    SlidingTabStrip(Context context, AttributeSet attrs) {
62
        super(context, attrs);
63
        setWillNotDraw(false);
64
 
65
        final float density = getResources().getDisplayMetrics().density;
66
 
67
        TypedValue outValue = new TypedValue();
68
        context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
69
        final int themeForegroundColor =  outValue.data;
70
 
71
        mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
72
                DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
73
 
74
        mDefaultTabColorizer = new SimpleTabColorizer();
75
        mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
76
        mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor,
77
                DEFAULT_DIVIDER_COLOR_ALPHA));
78
 
79
        mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
80
        mBottomBorderPaint = new Paint();
81
        mBottomBorderPaint.setColor(mDefaultBottomBorderColor);
82
 
83
        mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
84
        mSelectedIndicatorPaint = new Paint();
85
 
86
        mDividerHeight = DEFAULT_DIVIDER_HEIGHT;
87
        mDividerPaint = new Paint();
88
        mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density));
89
    }
90
 
91
    void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
92
        mCustomTabColorizer = customTabColorizer;
93
        invalidate();
94
    }
95
 
96
    void setSelectedIndicatorColors(int... colors) {
97
        // Make sure that the custom colorizer is removed
98
        mCustomTabColorizer = null;
99
        mDefaultTabColorizer.setIndicatorColors(colors);
100
        invalidate();
101
    }
102
 
103
    void setDividerColors(int... colors) {
104
        // Make sure that the custom colorizer is removed
105
        mCustomTabColorizer = null;
106
        mDefaultTabColorizer.setDividerColors(colors);
107
        invalidate();
108
    }
109
 
110
    void onViewPagerPageChanged(int position, float positionOffset) {
111
        mSelectedPosition = position;
112
        mSelectionOffset = positionOffset;
113
        invalidate();
114
    }
115
 
116
    @Override
117
    protected void onDraw(Canvas canvas) {
118
        final int height = getHeight();
119
        final int childCount = getChildCount();
120
        final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height);
121
        final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
122
                ? mCustomTabColorizer
123
                : mDefaultTabColorizer;
124
 
125
        // Thick colored underline below the current selection
126
        if (childCount > 0) {
127
            View selectedTitle = getChildAt(mSelectedPosition);
128
            int left = selectedTitle.getLeft();
129
            int right = selectedTitle.getRight();
130
            int color = tabColorizer.getIndicatorColor(mSelectedPosition);
131
 
132
            if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
133
                int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
134
                if (color != nextColor) {
135
                    color = blendColors(nextColor, color, mSelectionOffset);
136
                }
137
 
138
                // Draw the selection partway between the tabs
139
                View nextTitle = getChildAt(mSelectedPosition + 1);
140
                left = (int) (mSelectionOffset * nextTitle.getLeft() +
141
                        (1.0f - mSelectionOffset) * left);
142
                right = (int) (mSelectionOffset * nextTitle.getRight() +
143
                        (1.0f - mSelectionOffset) * right);
144
            }
145
 
146
            mSelectedIndicatorPaint.setColor(color);
147
 
148
            canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
149
                    height, mSelectedIndicatorPaint);
150
        }
151
 
152
        // Thin underline along the entire bottom edge
153
        canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
154
 
155
        // Vertical separators between the titles
156
        int separatorTop = (height - dividerHeightPx) / 2;
157
        for (int i = 0; i < childCount - 1; i++) {
158
            View child = getChildAt(i);
159
            mDividerPaint.setColor(tabColorizer.getDividerColor(i));
160
            canvas.drawLine(child.getRight(), separatorTop, child.getRight(),
161
                    separatorTop + dividerHeightPx, mDividerPaint);
162
        }
163
    }
164
 
165
    /**
166
     * Set the alpha value of the {@code color} to be the given {@code alpha} value.
167
     */
168
    private static int setColorAlpha(int color, byte alpha) {
169
        return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
170
    }
171
 
172
    /**
173
     * Blend {@code color1} and {@code color2} using the given ratio.
174
     *
175
     * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,
176
     *              0.0 will return {@code color2}.
177
     */
178
    private static int blendColors(int color1, int color2, float ratio) {
179
        final float inverseRation = 1f - ratio;
180
        float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
181
        float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
182
        float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
183
        return Color.rgb((int) r, (int) g, (int) b);
184
    }
185
 
186
    private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
187
        private int[] mIndicatorColors;
188
        private int[] mDividerColors;
189
 
190
        @Override
191
        public final int getIndicatorColor(int position) {
192
            return mIndicatorColors[position % mIndicatorColors.length];
193
        }
194
 
195
        @Override
196
        public final int getDividerColor(int position) {
197
            return mDividerColors[position % mDividerColors.length];
198
        }
199
 
200
        void setIndicatorColors(int... colors) {
201
            mIndicatorColors = colors;
202
        }
203
 
204
        void setDividerColors(int... colors) {
205
            mDividerColors = colors;
206
        }
207
    }
208
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.