Android Open Source - InfinitePager Sliding Tab Layout






From Project

Back to project page InfinitePager.

License

The source code is released under:

Apache License

If you think the Android project InfinitePager listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2013 The Android Open Source Project
 *// w  ww  . j  a va  2  s. co m
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.support.v4.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.github.paradam.infinitepager.InfinitePagerAdapter;
import com.github.paradam.infinitepager.InfiniteViewPager;
import com.github.paradam.infinitepager.R;

/**
 * To be used with ViewPager to provide a tab indicator component which give constant feedback as to
 * the user's scroll progress.
 * <p>
 * To use the component, simply add it to your view hierarchy. Then in your
 * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call
 * {@link #setViewPager(android.support.v4.view.ViewPager)} providing it the ViewPager this layout is being used for.
 * <p>
 * The colors can be customized in two ways. The first and simplest is to provide an array of colors
 * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The
 * alternative is via the {@link SlidingTabLayout.TabColorizer} interface which provides you complete control over
 * which color is used for any individual position.
 * <p>
 * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)},
 * providing the layout ID of your custom layout.
 *
 * Based off the developer.android.com sample code "SlidingTabsColors" (http://developer.android.com/samples/SlidingTabsColors/index.html)
 * with a few additions.
 */
public class SlidingTabLayout extends HorizontalScrollView implements SlidablePagerTitle, View.OnTouchListener, ViewPager.Decor {

    /**
     * Level of hidability of the TabLayout
     *
     * @see #HIDE_NONE
     * @see #HIDE_AUTO
     * @see #HIDE_PROGRAM
     */
    private int hidable = HIDE_NONE;

    /**
     * The PagerTitleStrip is currently collapsed and hidden at the top of the View.
     */
    private static final int CLOSED       = 0;
    /**
     * The PagerTitleStrip is currently sliding down to become visible to the user.
     */
    private static final int SLIDING_DOWN = 1;
    /**
     * The PagerTitleStrip is currently open and visible to the user.
     */
    private static final int OPEN         = 2;
    /**
     * The PagerTitleStrip is in the process of collapsing to be hidden from the user.
     */
    private static final int SLIDING_UP   = 3;

    /**
     * The state of the PagerTitleStrip.
     *
     * @see #CLOSED
     * @see #SLIDING_DOWN
     * @see #OPEN
     * @see #SLIDING_UP
     */
    private int slideState = OPEN;

    /**
     * A Runnable to be run after a delay that will trigger the PagerTitleStrip to collapse upwards
     * and hide from the user.
     */
    private final Runnable slideUp = new Runnable() {
        @Override
        public void run() {
            slideOut();
        }
    };

    /**
     * The id of the ViewPager this PagerTitleStrip is connected to.
     */
    private int mPagerId;

    /**
     * The duration the tabs will remain visible until they are hidden.
     *
     * Only honored if {@link #hidable} is set to {@link #HIDE_AUTO}. Ignored otherwise.
     */
    private long defaultDisplayTime = DISPLAY_TIME;

    private static final int[] ATTRS = new int[] {
            android.R.attr.textAppearance,
            android.R.attr.textSize,
            android.R.attr.textColor,
            android.R.attr.gravity,
            R.attr.viewPager,
            R.attr.autoHide,
            R.attr.dividerColors,
            R.attr.selectorColors,
            R.attr.displayDuration
    };

    /**
     * Allows complete control over the colors drawn in the tab layout. Set with
     * {@link #setCustomTabColorizer(SlidingTabLayout.TabColorizer)}.
     */
    public interface TabColorizer {

        /**
         * @return return the color of the indicator used when {@code position} is selected.
         */
        int getIndicatorColor(int position);

        /**
         * @return return the color of the divider drawn to the right of {@code position}.
         */
        int getDividerColor(int position);

    }

    /**
     * An observer that is informed when the data for the adapter changes.
     */
    private DataSetObserver dataChangeObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            populateTabStrip();
            SlidingTabLayout.this.post(new Runnable() {
                @Override
                public void run() {
                    scrollToTab(mViewPager instanceof InfiniteViewPager ? ((InfiniteViewPager) mViewPager).getRelativeCurrentItem() : mViewPager.getCurrentItem(), 0);
                }
            });
        }

        @Override
        public void onInvalidated() {
            populateTabStrip();
            SlidingTabLayout.this.post(new Runnable() {
                @Override
                public void run() {
                    scrollToTab(mViewPager instanceof InfiniteViewPager ? ((InfiniteViewPager) mViewPager).getRelativeCurrentItem() : mViewPager.getCurrentItem(), 0);
                }
            });
        }
    };

    private static final int TITLE_OFFSET_DIPS     = 24;
    private static final int TAB_VIEW_PADDING_DIPS = 16;
    private static final int TAB_VIEW_TEXT_SIZE_SP = 12;

    private int mTitleOffset;

    private int mTabViewLayoutId;
    private int mTabViewTextViewId;

    private ViewPager mViewPager;
    private final PageListener mPageListener = new PageListener();

    private final SlidingTabStrip mTabStrip;

    private int mTextAppearance;
    private int mTextSize;
    private int mTextColor;
    private int mGravity;

    public SlidingTabLayout(Context context) {
        this(context, null);
    }

    public SlidingTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTabStrip = new SlidingTabStrip(context, attrs);
        init(context, attrs);
    }

    public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mTabStrip = new SlidingTabStrip(context, attrs);
        init(context, attrs);
    }

    /**
     * Initialise the settings provided from the inflated XML.
     * @param context The context the layout was created in.
     * @param attrs The attribute set to get the settings from.
     */
    private void init(Context context, AttributeSet attrs) {
        // Disable the Scroll Bar
        setHorizontalScrollBarEnabled(false);
        // Make sure that the Tab Strips fills this View
        setFillViewport(true);

        mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);

        addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

        final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
        mTextAppearance = a.getResourceId(0, 0);
        mTextSize = a.getDimensionPixelSize(1, 0);
        if (a.hasValue(2)) {
            mTextColor = a.getColor(2, 0);
        }
        mGravity = a.getInteger(3, Gravity.BOTTOM);

        if (a.hasValue(4)) {
            mPagerId = a.getResourceId(4, 0);
        }

        if (a.hasValue(5)) {
            hidable = a.getInt(5, HIDE_NONE);
        }

        if (a.hasValue(6)) {
            setDividerColors(context.getResources().getIntArray(a.getResourceId(6, 0)));
        }

        if (a.hasValue(7)) {
            setSelectedIndicatorColors(context.getResources().getIntArray(a.getResourceId(7, 0)));
        }

        if (a.hasValue(8)) {
            defaultDisplayTime = a.getInteger(8, (int)DISPLAY_TIME);
        }
        a.recycle();

        setOnTouchListener(actionEventTouchListener);

        super.setBackgroundResource(0);
    }

    private OnTouchListener actionEventTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    SlidingTabLayout.this.removeCallbacks(slideUp);
                    if (hidable == HIDE_AUTO) {
                        SlidingTabLayout.this.postDelayed(slideUp, defaultDisplayTime);
                    }
            }
            return false;
        }
    };

    /**
     * @return The state of the Tab Layouts hidable status.
     *
     * @see #HIDE_NONE
     * @see #HIDE_AUTO
     * @see #HIDE_PROGRAM
     */
    public int isAutoHidable() {
        return hidable;
    }

    /**
     * Set the length in time the view will remain visible for.
     * @param displayTime The number of milliseconds to have the SlidingTabLayout visible for.
     */
    public void setDisplayTime(long displayTime) {
        defaultDisplayTime = displayTime;
    }

    /**
     * Get the number of milliseconds the SlidingTabLayout will remain visible for if {@link #isAutoHidable()}
     * equals {@link #HIDE_AUTO}.
     */
    public long getDisplayTime() {
        return defaultDisplayTime;
    }

    /**
     * Set if this TabLayout can auto hide to conserve less space.
     * <br />
     * Note: Setting this to {@link #HIDE_NONE} can lock the Tab Layout into an open or closed state.
     * @param autoHide The state of the Tab Layouts hidability. {@link #HIDE_NONE} for not hidable at all,
     *                 {@link #HIDE_PROGRAM} for hidable only when {@link #slideIn(long)} or {@link #slideOut(long)}
     *                 are called, or {@link #HIDE_AUTO} for automatic control.
     *
     * @see #HIDE_NONE
     * @see #HIDE_AUTO
     * @see #HIDE_PROGRAM
     */
    public void setAutoHidable(int autoHide) {
        hidable = autoHide;
        if (autoHide == HIDE_NONE) {
            removeCallbacks(slideUp);
        } else if (autoHide == HIDE_AUTO && (slideState == OPEN || slideState == SLIDING_DOWN)) {
            removeCallbacks(slideUp);
            postDelayed(slideUp, defaultDisplayTime);
        }
    }

    @TargetApi (Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void setBackground(Drawable background) {
        mTabStrip.setBackground(background);
    }

    @Override
    public void setBackgroundColor(int color) {
        mTabStrip.setBackgroundColor(color);
    }

    @Override
    public void setBackgroundResource(int resid) {
        mTabStrip.setBackgroundResource(resid);
    }

    /**
     * Set the custom {@link SlidingTabLayout.TabColorizer} to be used.
     *
     * If you only require simple custmisation then you can use
     * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve
     * similar effects.
     */
    public void setCustomTabColorizer(TabColorizer tabColorizer) {
        mTabStrip.setCustomTabColorizer(tabColorizer);
    }

    /**
     * Sets the colors to be used for indicating the selected tab. These colors are treated as a
     * circular array. Providing one color will mean that all tabs are indicated with the same color.
     */
    public void setSelectedIndicatorColors(int... colors) {
        mTabStrip.setSelectedIndicatorColors(colors);
    }

    /**
     * Sets the colors to be used for tab dividers. These colors are treated as a circular array.
     * Providing one color will mean that all tabs are indicated with the same color.
     */
    public void setDividerColors(int... colors) {
        mTabStrip.setDividerColors(colors);
    }

    /**
     * Set the custom layout to be inflated for the tab views.
     *
     * @param layoutResId Layout id to be inflated
     * @param textViewId id of the {@link android.widget.TextView} in the inflated view
     */
    public void setCustomTabView(int layoutResId, int textViewId) {
        mTabViewLayoutId = layoutResId;
        mTabViewTextViewId = textViewId;
    }

    /**
     * Sets the associated view pager. Note that the assumption here is that the pager content
     * (number of tabs and tab titles) does not change after this call has been made.
     */
    public void setViewPager(ViewPager viewPager) {
        if (viewPager == mViewPager) {
            return;
        }
        if (mViewPager != null) {
            mViewPager.setInternalPageChangeListener(null);
            mViewPager.setOnAdapterChangeListener(null);
            mViewPager.setOnTouchListener(null);
            PagerAdapter adapter = mViewPager.getAdapter();
            if (adapter != null) {
                adapter.unregisterDataSetObserver(dataChangeObserver);
            }
        }
        mTabStrip.removeAllViews();
        mViewPager = viewPager;
        if (mViewPager == null) {
            return;
        }

        mViewPager.setInternalPageChangeListener(mPageListener);
        mViewPager.setOnAdapterChangeListener(mPageListener);
        mViewPager.setOnTouchListener(this);

        PagerAdapter adapter = mViewPager.getAdapter();
        if (adapter != null) {
            adapter.registerDataSetObserver(dataChangeObserver);
            populateTabStrip();
            SlidingTabLayout.this.post(new Runnable() {
                @Override
                public void run() {
                    scrollToTab(mViewPager instanceof InfiniteViewPager ? ((InfiniteViewPager) mViewPager).getRelativeCurrentItem() : mViewPager.getCurrentItem(), 0);
                }
            });
        }
        if (hidable == HIDE_AUTO) {
            slideState = OPEN;
            this.setVisibility(View.VISIBLE);
            this.postDelayed(slideUp, defaultDisplayTime);
        }
    }

    /**
     * Create a default view to be used for tabs. This is called if a custom tab view is not set via
     * {@link #setCustomTabView(int, int)}.
     */
    protected TextView createDefaultTabView(Context context) {
        TextView textView = new TextView(context);
        textView.setTextAppearance(context, mTextAppearance);
        textView.setGravity(mGravity > 0 ? mGravity : Gravity.CENTER);
        if (mTextSize > 0) {
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
        } else {
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
        }
        if (mTextColor != 0) {
            textView.setTextColor(mTextColor);
        }
        textView.setTypeface(Typeface.DEFAULT_BOLD);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // If we're running on Honeycomb or newer, then we can use the Theme's
            // selectableItemBackground to ensure that the View has a pressed state
            TypedValue outValue = new TypedValue();
            getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
            textView.setBackgroundResource(outValue.resourceId);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style
            textView.setAllCaps(true);
        }

        int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
        textView.setPadding(padding, padding, padding, padding);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        lp.weight = 1f;
        textView.setLayoutParams(lp);

        return textView;
    }

    /**
     * Find and create a set of TextViews to insert into the TabStrip.
     */
    protected void populateTabStrip() {
        mTabStrip.removeAllViews();
        if (mViewPager != null) {
            final PagerAdapter adapter = mViewPager.getAdapter();
            if (adapter != null) {
                final OnClickListener tabClickListener = new TabClickListener();

                final boolean isInfinitePager = adapter instanceof InfinitePagerAdapter;
                int length = (isInfinitePager ? ((InfinitePagerAdapter) adapter).getRelativeCount() : adapter.getCount());
                for (int i = 0; i < length; i++) {
                    View tabView = null;
                    TextView tabTitleView = null;

                    if (mTabViewLayoutId != 0) {
                        // If there is a custom tab view layout id set, try and inflate it
                        tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip, false);
                        tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
                    }

                    if (tabView == null) {
                        tabView = createDefaultTabView(getContext());
                    }

                    if (tabTitleView == null && TextView.class.isInstance(tabView)) {
                        tabTitleView = (TextView) tabView;
                    }

                    if (tabTitleView != null) {
                        tabTitleView.setGravity(Gravity.CENTER);
                        tabTitleView.setText(isInfinitePager ? ((InfinitePagerAdapter) adapter).getRelativePageTitle(i) : adapter.getPageTitle(i));
                    }
                    tabView.setOnClickListener(tabClickListener);
                    tabView.setOnTouchListener(actionEventTouchListener);

                    mTabStrip.addView(tabView);
                }
            }
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        ViewParent parent = getParent();
        if (mPagerId != 0) {
            View related = ((ViewGroup)parent).findViewById(mPagerId);
            if (!(related instanceof ViewPager)) {
                throw new IllegalStateException(
                        "ViewPager ID is does not refer to ViewPager.");
            }
            parent = (ViewParent) related;
        } else if (!(parent instanceof ViewPager)) {
            // Parent has not been set, will wait for #setViewPager(ViewPager) to be called instead.
            return;
        }

        setViewPager((ViewPager) parent);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setViewPager(null);
    }

    private void scrollToTab(int tabIndex, int positionOffset) {
        final int tabStripChildCount = mTabStrip.getChildCount();
        if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
            return;
        }
        View selectedChild = mTabStrip.getChildAt(tabIndex);
        if (selectedChild != null && (float)positionOffset / selectedChild.getWidth() > 0.5 && tabIndex == tabStripChildCount -1) {
            tabIndex = 0;
            positionOffset = 0;
        }
        selectedChild = mTabStrip.getChildAt(tabIndex);
        if (selectedChild != null) {
            int targetScrollX = selectedChild.getLeft() + positionOffset;

            if (tabIndex > 0 || positionOffset > 0) {
                // If we're not at the first child and are mid-scroll, make sure we obey the offset
                targetScrollX -= mTitleOffset;
            }

            scrollTo(targetScrollX, 0);
        }
    }

    private class TabClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                if (v == mTabStrip.getChildAt(i)) {
                    if (mViewPager instanceof InfiniteViewPager) {
                        ((InfiniteViewPager)mViewPager).setRelativeCurrentItem(i);
                    } else {
                        mViewPager.setCurrentItem(i);
                    }
                    return;
                }
            }
        }
    }


    /**
     * Slide up the view to remove it from the frame.
     */
    private void slideOut() {
        if (slideState == OPEN) {
            slideState = SLIDING_UP;
            Animation slideOut = AnimationUtils.loadAnimation(this.getContext(), R.anim.abc_slide_out_top);
            slideOut.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationEnd(Animation animation) {
                    if (slideState != SLIDING_UP) {
                        slideState = CLOSED;
                        slideIn();
                    } else {
                        slideState = CLOSED;
                    }
                    SlidingTabLayout.this.setVisibility(View.GONE);
                }

                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });
            this.startAnimation(slideOut);
        }
    }

    /**
     * Slide down the view so that its contents are visible and can be interacted with.
     */
    private void slideIn() {
        if (slideState == CLOSED) {
            slideState = SLIDING_DOWN;
            Animation slideIn = AnimationUtils.loadAnimation(this.getContext(), R.anim.abc_slide_in_top);
            slideIn.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationEnd(Animation animation) {
                    slideState = OPEN;
                }

                @Override
                public void onAnimationStart(Animation animation) {
                    SlidingTabLayout.this.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });
            this.startAnimation(slideIn);
        }
    }

    /**
     * The last position of the pointer in the Y axis.
     */
    private float downPositionY = -1;

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        if (hidable == HIDE_AUTO) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downPositionY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (downPositionY + MOVE_THRESHOLD < event.getY()) {
                        if (slideState == CLOSED) {
                            slideIn(defaultDisplayTime);
                        }
                    } else if (downPositionY - MOVE_THRESHOLD > event.getY()) {
                        if (slideState == OPEN || slideState == SLIDING_DOWN) {
                            slideOut(0);
                        }
                    }
                    break;
            }
        }
        return false;
    }

    @Override
    public void slideIn(long milliseconds) {
        if (hidable == HIDE_NONE) { return; }
        if (slideState == CLOSED) {
            slideIn();
        } else {
            slideState = OPEN;
        }
        removeCallbacks(slideUp);
        if (milliseconds >= 0 && hidable == HIDE_AUTO) {
            postDelayed(slideUp, milliseconds);
        }
    }

    @Override
    public void slideOut(long milliseconds) {
        if (hidable == HIDE_NONE) { return; }
        if (slideState == CLOSED || slideState == SLIDING_UP) { return; }
        removeCallbacks(slideUp);
        slideState = OPEN;
        if (milliseconds > 0) {
            postDelayed(slideUp, milliseconds);
        } else {
            post(slideUp);
        }
    }

    private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
            ViewPager.OnAdapterChangeListener {
        private int mScrollState;

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (hidable == HIDE_AUTO) {
                if (slideState == CLOSED) {
                    slideIn();
                    SlidingTabLayout.this.removeCallbacks(slideUp);
                    if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                        SlidingTabLayout.this.postDelayed(slideUp, DISPLAY_TIME_SHORT);
                    }
                } else if (slideState == SLIDING_UP) {
                    slideState = OPEN;
                } else {
                    SlidingTabLayout.this.removeCallbacks(slideUp);
                    SlidingTabLayout.this.postDelayed(slideUp, DISPLAY_TIME_SHORT);
                }
            }

            int tabStripChildCount = mTabStrip.getChildCount();
            if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
                return;
            }

            mTabStrip.onViewPagerPageChanged(position, positionOffset);

            View selectedTitle = mTabStrip.getChildAt(position);
            int extraOffset = (selectedTitle != null)
                              ? (int) (positionOffset * selectedTitle.getWidth())
                              : 0;
            scrollToTab(position, extraOffset);
        }

        @Override
        public void onPageSelected(int position) {
            if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                mTabStrip.onViewPagerPageChanged(position, 0f);
                scrollToTab(position, 0);
            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            mScrollState = state;
        }

        @Override
        public void onAdapterChanged(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
            if (oldAdapter != null) {
                oldAdapter.unregisterDataSetObserver(dataChangeObserver);
            }
            if (newAdapter != null ) {
                newAdapter.registerDataSetObserver(dataChangeObserver);
            }
            populateTabStrip();
        }

        @Override
        public void onChanged() {
            populateTabStrip();
        }
    }
}




Java Source Code List

android.support.v4.view.SlidablePagerTitle.java
android.support.v4.view.SlidingTabLayout.java
android.support.v4.view.SlidingTabStrip.java
com.github.paradam.infinitepager.InfiniteFragmentPagerAdapter.java
com.github.paradam.infinitepager.InfiniteFragmentStatePagerAdapter.java
com.github.paradam.infinitepager.InfinitePagerAdapter.java
com.github.paradam.infinitepager.InfiniteViewPager.java
com.github.paradam.infinitepager.demo.v4.InfiniteFragmentStatePagerActivity.java
com.github.paradam.support.v4.infinitepager.InfiniteFragmentPagerAdapter.java
com.github.paradam.support.v4.infinitepager.InfiniteFragmentStatePagerAdapter.java