Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)
SwipeRefreshMultipleViews / src / com.example.android.common / view /

SlidingTabLayout.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.content.Context;
       
       
        20
       
       
        import android.graphics.Typeface;
       
       
        21
       
       
        import android.os.Build;
       
       
        22
       
       
        import android.support.v4.view.PagerAdapter;
       
       
        23
       
       
        import android.support.v4.view.ViewPager;
       
       
        24
       
       
        import android.util.AttributeSet;
       
       
        25
       
       
        import android.util.TypedValue;
       
       
        26
       
       
        import android.view.Gravity;
       
       
        27
       
       
        import android.view.LayoutInflater;
       
       
        28
       
       
        import android.view.View;
       
       
        29
       
       
        import android.widget.HorizontalScrollView;
       
       
        30
       
       
        import android.widget.TextView;
       
       
        31
       
       
       
       
        32
       
       
        /**
       
       
        33
       
       
        * To be used with ViewPager to provide a tab indicator component which give constant feedback as to
       
       
        34
       
       
        * the user's scroll progress.
       
       
        35
       
       
        * <p>
       
       
        36
       
       
        * To use the component, simply add it to your view hierarchy. Then in your
       
       
        37
       
       
        * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call
       
       
        38
       
       
        * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for.
       
       
        39
       
       
        * <p>
       
       
        40
       
       
        * The colors can be customized in two ways. The first and simplest is to provide an array of colors
       
       
        41
       
       
        * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The
       
       
        42
       
       
        * alternative is via the {@link TabColorizer} interface which provides you complete control over
       
       
        43
       
       
        * which color is used for any individual position.
       
       
        44
       
       
        * <p>
       
       
        45
       
       
        * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)},
       
       
        46
       
       
        * providing the layout ID of your custom layout.
       
       
        47
       
       
        */
       
       
        48
       
       
        public class SlidingTabLayout extends HorizontalScrollView {
       
       
        49
       
       
       
       
        50
       
       
        /**
       
       
        51
       
       
        * Allows complete control over the colors drawn in the tab layout. Set with
       
       
        52
       
       
        * {@link #setCustomTabColorizer(TabColorizer)}.
       
       
        53
       
       
        */
       
       
        54
       
       
        public interface TabColorizer {
       
       
        55
       
       
       
       
        56
       
       
        /**
       
       
        57
       
       
        * @return return the color of the indicator used when {@code position} is selected.
       
       
        58
       
       
        */
       
       
        59
       
       
        int getIndicatorColor(int position);
       
       
        60
       
       
       
       
        61
       
       
        /**
       
       
        62
       
       
        * @return return the color of the divider drawn to the right of {@code position}.
       
       
        63
       
       
        */
       
       
        64
       
       
        int getDividerColor(int position);
       
       
        65
       
       
       
       
        66
       
       
        }
       
       
        67
       
       
       
       
        68
       
       
        private static final int TITLE_OFFSET_DIPS = 24;
       
       
        69
       
       
        private static final int TAB_VIEW_PADDING_DIPS = 16;
       
       
        70
       
       
        private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
       
       
        71
       
       
       
       
        72
       
       
        private int mTitleOffset;
       
       
        73
       
       
       
       
        74
       
       
        private int mTabViewLayoutId;
       
       
        75
       
       
        private int mTabViewTextViewId;
       
       
        76
       
       
       
       
        77
       
       
        private ViewPager mViewPager;
       
       
        78
       
       
        private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
       
       
        79
       
       
       
       
        80
       
       
        private final SlidingTabStrip mTabStrip;
       
       
        81
       
       
       
       
        82
       
       
        public SlidingTabLayout(Context context) {
       
       
        83
       
       
        this(context, null);
       
       
        84
       
       
        }
       
       
        85
       
       
       
       
        86
       
       
        public SlidingTabLayout(Context context, AttributeSet attrs) {
       
       
        87
       
       
        this(context, attrs, 0);
       
       
        88
       
       
        }
       
       
        89
       
       
       
       
        90
       
       
        public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
       
       
        91
       
       
        super(context, attrs, defStyle);
       
       
        92
       
       
       
       
        93
       
       
        // Disable the Scroll Bar
       
       
        94
       
       
        setHorizontalScrollBarEnabled(false);
       
       
        95
       
       
        // Make sure that the Tab Strips fills this View
       
       
        96
       
       
        setFillViewport(true);
       
       
        97
       
       
       
       
        98
       
       
        mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
       
       
        99
       
       
       
       
        100
       
       
        mTabStrip = new SlidingTabStrip(context);
       
       
        101
       
       
        addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
       
       
        102
       
       
        }
       
       
        103
       
       
       
       
        104
       
       
        /**
       
       
        105
       
       
        * Set the custom {@link TabColorizer} to be used.
       
       
        106
       
       
        *
       
       
        107
       
       
        * If you only require simple custmisation then you can use
       
       
        108
       
       
        * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve
       
       
        109
       
       
        * similar effects.
       
       
        110
       
       
        */
       
       
        111
       
       
        public void setCustomTabColorizer(TabColorizer tabColorizer) {
       
       
        112
       
       
        mTabStrip.setCustomTabColorizer(tabColorizer);
       
       
        113
       
       
        }
       
       
        114
       
       
       
       
        115
       
       
        /**
       
       
        116
       
       
        * Sets the colors to be used for indicating the selected tab. These colors are treated as a
       
       
        117
       
       
        * circular array. Providing one color will mean that all tabs are indicated with the same color.
       
       
        118
       
       
        */
       
       
        119
       
       
        public void setSelectedIndicatorColors(int... colors) {
       
       
        120
       
       
        mTabStrip.setSelectedIndicatorColors(colors);
       
       
        121
       
       
        }
       
       
        122
       
       
       
       
        123
       
       
        /**
       
       
        124
       
       
        * Sets the colors to be used for tab dividers. These colors are treated as a circular array.
       
       
        125
       
       
        * Providing one color will mean that all tabs are indicated with the same color.
       
       
        126
       
       
        */
       
       
        127
       
       
        public void setDividerColors(int... colors) {
       
       
        128
       
       
        mTabStrip.setDividerColors(colors);
       
       
        129
       
       
        }
       
       
        130
       
       
       
       
        131
       
       
        /**
       
       
        132
       
       
        * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are
       
       
        133
       
       
        * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so
       
       
        134
       
       
        * that the layout can update it's scroll position correctly.
       
       
        135
       
       
        *
       
       
        136
       
       
        * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
       
       
        137
       
       
        */
       
       
        138
       
       
        public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
       
       
        139
       
       
        mViewPagerPageChangeListener = listener;
       
       
        140
       
       
        }
       
       
        141
       
       
       
       
        142
       
       
        /**
       
       
        143
       
       
        * Set the custom layout to be inflated for the tab views.
       
       
        144
       
       
        *
       
       
        145
       
       
        * @param layoutResId Layout id to be inflated
       
       
        146
       
       
        * @param textViewId id of the {@link TextView} in the inflated view
       
       
        147
       
       
        */
       
       
        148
       
       
        public void setCustomTabView(int layoutResId, int textViewId) {
       
       
        149
       
       
        mTabViewLayoutId = layoutResId;
       
       
        150
       
       
        mTabViewTextViewId = textViewId;
       
       
        151
       
       
        }
       
       
        152
       
       
       
       
        153
       
       
        /**
       
       
        154
       
       
        * Sets the associated view pager. Note that the assumption here is that the pager content
       
       
        155
       
       
        * (number of tabs and tab titles) does not change after this call has been made.
       
       
        156
       
       
        */
       
       
        157
       
       
        public void setViewPager(ViewPager viewPager) {
       
       
        158
       
       
        mTabStrip.removeAllViews();
       
       
        159
       
       
       
       
        160
       
       
        mViewPager = viewPager;
       
       
        161
       
       
        if (viewPager != null) {
       
       
        162
       
       
        viewPager.setOnPageChangeListener(new InternalViewPagerListener());
       
       
        163
       
       
        populateTabStrip();
       
       
        164
       
       
        }
       
       
        165
       
       
        }
       
       
        166
       
       
       
       
        167
       
       
        /**
       
       
        168
       
       
        * Create a default view to be used for tabs. This is called if a custom tab view is not set via
       
       
        169
       
       
        * {@link #setCustomTabView(int, int)}.
       
       
        170
       
       
        */
       
       
        171
       
       
        protected TextView createDefaultTabView(Context context) {
       
       
        172
       
       
        TextView textView = new TextView(context);
       
       
        173
       
       
        textView.setGravity(Gravity.CENTER);
       
       
        174
       
       
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
       
       
        175
       
       
        textView.setTypeface(Typeface.DEFAULT_BOLD);
       
       
        176
       
       
       
       
        177
       
       
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
       
       
        178
       
       
        // If we're running on Honeycomb or newer, then we can use the Theme's
       
       
        179
       
       
        // selectableItemBackground to ensure that the View has a pressed state
       
       
        180
       
       
        TypedValue outValue = new TypedValue();
       
       
        181
       
       
        getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
       
       
        182
       
       
        outValue, true);
       
       
        183
       
       
        textView.setBackgroundResource(outValue.resourceId);
       
       
        184
       
       
        }
       
       
        185
       
       
       
       
        186
       
       
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
       
       
        187
       
       
        // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style
       
       
        188
       
       
        textView.setAllCaps(true);
       
       
        189
       
       
        }
       
       
        190
       
       
       
       
        191
       
       
        int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
       
       
        192
       
       
        textView.setPadding(padding, padding, padding, padding);
       
       
        193
       
       
       
       
        194
       
       
        return textView;
       
       
        195
       
       
        }
       
       
        196
       
       
       
       
        197
       
       
        private void populateTabStrip() {
       
       
        198
       
       
        final PagerAdapter adapter = mViewPager.getAdapter();
       
       
        199
       
       
        final View.OnClickListener tabClickListener = new TabClickListener();
       
       
        200
       
       
       
       
        201
       
       
        for (int i = 0; i < adapter.getCount(); i++) {
       
       
        202
       
       
        View tabView = null;
       
       
        203
       
       
        TextView tabTitleView = null;
       
       
        204
       
       
       
       
        205
       
       
        if (mTabViewLayoutId != 0) {
       
       
        206
       
       
        // If there is a custom tab view layout id set, try and inflate it
       
       
        207
       
       
        tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
       
       
        208
       
       
        false);
       
       
        209
       
       
        tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
       
       
        210
       
       
        }
       
       
        211
       
       
       
       
        212
       
       
        if (tabView == null) {
       
       
        213
       
       
        tabView = createDefaultTabView(getContext());
       
       
        214
       
       
        }
       
       
        215
       
       
       
       
        216
       
       
        if (tabTitleView == null && TextView.class.isInstance(tabView)) {
       
       
        217
       
       
        tabTitleView = (TextView) tabView;
       
       
        218
       
       
        }
       
       
        219
       
       
       
       
        220
       
       
        tabTitleView.setText(adapter.getPageTitle(i));
       
       
        221
       
       
        tabView.setOnClickListener(tabClickListener);
       
       
        222
       
       
       
       
        223
       
       
        mTabStrip.addView(tabView);
       
       
        224
       
       
        }
       
       
        225
       
       
        }
       
       
        226
       
       
       
       
        227
       
       
        @Override
       
       
        228
       
       
        protected void onAttachedToWindow() {
       
       
        229
       
       
        super.onAttachedToWindow();
       
       
        230
       
       
       
       
        231
       
       
        if (mViewPager != null) {
       
       
        232
       
       
        scrollToTab(mViewPager.getCurrentItem(), 0);
       
       
        233
       
       
        }
       
       
        234
       
       
        }
       
       
        235
       
       
       
       
        236
       
       
        private void scrollToTab(int tabIndex, int positionOffset) {
       
       
        237
       
       
        final int tabStripChildCount = mTabStrip.getChildCount();
       
       
        238
       
       
        if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
       
       
        239
       
       
        return;
       
       
        240
       
       
        }
       
       
        241
       
       
       
       
        242
       
       
        View selectedChild = mTabStrip.getChildAt(tabIndex);
       
       
        243
       
       
        if (selectedChild != null) {
       
       
        244
       
       
        int targetScrollX = selectedChild.getLeft() + positionOffset;
       
       
        245
       
       
       
       
        246
       
       
        if (tabIndex > 0 || positionOffset > 0) {
       
       
        247
       
       
        // If we're not at the first child and are mid-scroll, make sure we obey the offset
       
       
        248
       
       
        targetScrollX -= mTitleOffset;
       
       
        249
       
       
        }
       
       
        250
       
       
       
       
        251
       
       
        scrollTo(targetScrollX, 0);
       
       
        252
       
       
        }
       
       
        253
       
       
        }
       
       
        254
       
       
       
       
        255
       
       
        private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
       
       
        256
       
       
        private int mScrollState;
       
       
        257
       
       
       
       
        258
       
       
        @Override
       
       
        259
       
       
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
       
       
        260
       
       
        int tabStripChildCount = mTabStrip.getChildCount();
       
       
        261
       
       
        if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
       
       
        262
       
       
        return;
       
       
        263
       
       
        }
       
       
        264
       
       
       
       
        265
       
       
        mTabStrip.onViewPagerPageChanged(position, positionOffset);
       
       
        266
       
       
       
       
        267
       
       
        View selectedTitle = mTabStrip.getChildAt(position);
       
       
        268
       
       
        int extraOffset = (selectedTitle != null)
       
       
        269
       
       
        ? (int) (positionOffset * selectedTitle.getWidth())
       
       
        270
       
       
        : 0;
       
       
        271
       
       
        scrollToTab(position, extraOffset);
       
       
        272
       
       
       
       
        273
       
       
        if (mViewPagerPageChangeListener != null) {
       
       
        274
       
       
        mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
       
       
        275
       
       
        positionOffsetPixels);
       
       
        276
       
       
        }
       
       
        277
       
       
        }
       
       
        278
       
       
       
       
        279
       
       
        @Override
       
       
        280
       
       
        public void onPageScrollStateChanged(int state) {
       
       
        281
       
       
        mScrollState = state;
       
       
        282
       
       
       
       
        283
       
       
        if (mViewPagerPageChangeListener != null) {
       
       
        284
       
       
        mViewPagerPageChangeListener.onPageScrollStateChanged(state);
       
       
        285
       
       
        }
       
       
        286
       
       
        }
       
       
        287
       
       
       
       
        288
       
       
        @Override
       
       
        289
       
       
        public void onPageSelected(int position) {
       
       
        290
       
       
        if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
       
       
        291
       
       
        mTabStrip.onViewPagerPageChanged(position, 0f);
       
       
        292
       
       
        scrollToTab(position, 0);
       
       
        293
       
       
        }
       
       
        294
       
       
       
       
        295
       
       
        if (mViewPagerPageChangeListener != null) {
       
       
        296
       
       
        mViewPagerPageChangeListener.onPageSelected(position);
       
       
        297
       
       
        }
       
       
        298
       
       
        }
       
       
        299
       
       
       
       
        300
       
       
        }
       
       
        301
       
       
       
       
        302
       
       
        private class TabClickListener implements View.OnClickListener {
       
       
        303
       
       
        @Override
       
       
        304
       
       
        public void onClick(View v) {
       
       
        305
       
       
        for (int i = 0; i < mTabStrip.getChildCount(); i++) {
       
       
        306
       
       
        if (v == mTabStrip.getChildAt(i)) {
       
       
        307
       
       
        mViewPager.setCurrentItem(i);
       
       
        308
       
       
        return;
       
       
        309
       
       
        }
       
       
        310
       
       
        }
       
       
        311
       
       
        }
       
       
        312
       
       
        }
       
       
        313
       
       
       
       
        314
       
       
        }