com.ring.widget.PagerSlidingTabStrip.java Source code

Java tutorial

Introduction

Here is the source code for com.ring.widget.PagerSlidingTabStrip.java

Source

/*
 * Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me>
 * 
 * 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 com.ring.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.example.randomringapp.R;

/**
 * ViewPager? HOME URLhttp://github.com/xiaopansky/Android-PagerSlidingTabStrip
 * @version 1.3.0
 * @author Peng fei Pan
 */
public class PagerSlidingTabStrip extends HorizontalScrollView implements View.OnClickListener {
    private int currentPosition; //??
    private int lastOffset;
    private int lastScrollX = 0;
    private float currentPositionOffset; //?????
    private boolean start;
    private boolean allowWidthFull; // ?Item
    private boolean disableViewPager; // ?ViewPager
    private View currentSelectedTabView; //?
    private Drawable slidingBlockDrawable; //?
    private ViewPager viewPager; //ViewPager
    private ViewGroup tabsLayout; //
    private ViewPager.OnPageChangeListener onPageChangeListener; //???
    private OnClickTabListener onClickTabListener;
    private List<View> tabViews;
    private boolean disableTensileSlidingBlock; // ??
    private boolean isAllowDivider;
    private int barColor = 0xFF666666;
    private int underlineColor = 0x1A000000;
    private int dividerColor = 0x1A000000;
    private int dividerWidth = 1;
    private int dividerPadding = 12;
    private Paint rectPaint;
    private Paint dividerPaint;
    private int barHeight = 8;
    private int underLineHeight = 2;

    public PagerSlidingTabStrip(Context context) {
        this(context, null);

    }

    public PagerSlidingTabStrip(Context context, AttributeSet attrs) {
        super(context, attrs);
        setHorizontalScrollBarEnabled(false); //??????

        if (attrs != null) {
            TypedArray attrsTypedArray = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip);
            if (attrsTypedArray != null) {
                allowWidthFull = attrsTypedArray.getBoolean(R.styleable.PagerSlidingTabStrip_allowWidthFull, false);
                slidingBlockDrawable = attrsTypedArray.getDrawable(R.styleable.PagerSlidingTabStrip_slidingBlock);
                disableViewPager = attrsTypedArray.getBoolean(R.styleable.PagerSlidingTabStrip_disableViewPager,
                        false);
                disableTensileSlidingBlock = attrsTypedArray
                        .getBoolean(R.styleable.PagerSlidingTabStrip_disableTensileSlidingBlock, false);
                attrsTypedArray.recycle();
            }
        }
        init();
    }

    private void init() {

        DisplayMetrics dm = getResources().getDisplayMetrics();

        barHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, barHeight, dm);
        underLineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, underLineHeight, dm);
        dividerPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm);
        rectPaint = new Paint();
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(Style.FILL);
        dividerPaint = new Paint();
        dividerPaint.setAntiAlias(true);
        dividerPaint.setStrokeWidth(dividerWidth);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (!allowWidthFull)
            return;
        ViewGroup tabsLayout = getTabsLayout();
        if (tabsLayout == null || tabsLayout.getMeasuredWidth() >= getMeasuredWidth())
            return;
        if (tabsLayout.getChildCount() <= 0)
            return;

        if (tabViews == null) {
            tabViews = new ArrayList<View>();
        } else {
            tabViews.clear();
        }
        for (int w = 0; w < tabsLayout.getChildCount(); w++) {
            tabViews.add(tabsLayout.getChildAt(w));
        }

        adjustChildWidthWithParent(tabViews,
                getMeasuredWidth() - tabsLayout.getPaddingLeft() - tabsLayout.getPaddingRight(), widthMeasureSpec,
                heightMeasureSpec);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * views?ViewView?parentViewWidth
     * @param views ?View?
     * @param parentViewWidth Vie
     * @param parentWidthMeasureSpec View
     * @param parentHeightMeasureSpec View
     */
    private void adjustChildWidthWithParent(List<View> views, int parentViewWidth, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        // ?View?
        for (View view : views) {
            if (view.getLayoutParams() instanceof MarginLayoutParams) {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
                parentViewWidth -= lp.leftMargin + lp.rightMargin;
            }
        }

        // ?View???
        int averageWidth = parentViewWidth / views.size();
        int bigTabCount = views.size();
        while (true) {
            Iterator<View> iterator = views.iterator();
            while (iterator.hasNext()) {
                View view = iterator.next();
                if (view.getMeasuredWidth() > averageWidth) {
                    parentViewWidth -= view.getMeasuredWidth();
                    bigTabCount--;
                    iterator.remove();
                }
            }
            averageWidth = parentViewWidth / bigTabCount;
            boolean end = true;
            for (View view : views) {
                if (view.getMeasuredWidth() > averageWidth) {
                    end = false;
                }
            }
            if (end) {
                break;
            }
        }

        // ??View
        for (View view : views) {
            if (view.getMeasuredWidth() < averageWidth) {
                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams();
                layoutParams.width = averageWidth;
                view.setLayoutParams(layoutParams);
                // ??
                if (layoutParams instanceof MarginLayoutParams) {
                    measureChildWithMargins(view, parentWidthMeasureSpec, 0, parentHeightMeasureSpec, 0);
                } else {
                    measureChild(view, parentWidthMeasureSpec, parentHeightMeasureSpec);
                }
            }
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        ViewGroup tabViewGroup = getTabsLayout();
        if (tabViewGroup != null) {
            // ?????
            currentPosition = viewPager != null ? viewPager.getCurrentItem() : 0;
            if (!disableViewPager) {
                scrollToChild(currentPosition, 0); //??
                selectedTab(currentPosition); //?TAB
            }

            //?tab?Pager
            for (int w = 0; w < tabViewGroup.getChildCount(); w++) {
                View itemView = tabViewGroup.getChildAt(w);
                itemView.setTag(w);
                itemView.setOnClickListener(this);
            }
        }
    }

    @Override
    public void onClick(View v) {
        int index = (Integer) v.getTag();
        if (onClickTabListener != null) {
            onClickTabListener.onClickTab(v, index);
        }
        if (viewPager != null) {
            viewPager.setCurrentItem(index, true);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (disableViewPager)
            return;

        /* ? */
        ViewGroup tabsLayout = getTabsLayout();
        int tabCount = tabsLayout.getChildCount();
        if (tabsLayout == null || tabCount == 0) {
            return;
        }

        View currentTab = tabsLayout.getChildAt(currentPosition);
        if (currentTab == null) {
            return;
        }
        int height = getHeight();
        float slidingBlockLeft = currentTab.getLeft();
        float slidingBlockRight = currentTab.getRight();
        if (currentPositionOffset > 0f && currentPosition < tabsLayout.getChildCount() - 1) {
            View nextTab = tabsLayout.getChildAt(currentPosition + 1);
            if (nextTab != null) {
                final float nextTabLeft = nextTab.getLeft();
                final float nextTabRight = nextTab.getRight();
                slidingBlockLeft = (currentPositionOffset * nextTabLeft
                        + (1f - currentPositionOffset) * slidingBlockLeft);
                slidingBlockRight = (currentPositionOffset * nextTabRight
                        + (1f - currentPositionOffset) * slidingBlockRight);
            }
        }
        if (slidingBlockDrawable != null) {
            // ?
            if (disableTensileSlidingBlock) {
                int center = (int) (slidingBlockLeft + (slidingBlockRight - slidingBlockLeft) / 2);
                slidingBlockLeft = center - slidingBlockDrawable.getIntrinsicWidth() / 2;
                slidingBlockRight = center + slidingBlockDrawable.getIntrinsicWidth() / 2;
            }

            slidingBlockDrawable.setBounds((int) slidingBlockLeft,
                    getHeight() - slidingBlockDrawable.getIntrinsicHeight(), (int) slidingBlockRight, getHeight());
            slidingBlockDrawable.draw(canvas);
        } else {

            rectPaint.setColor(barColor);

            canvas.drawRect(slidingBlockLeft, height - barHeight, slidingBlockRight, height, rectPaint);
            rectPaint.setColor(underlineColor);
            canvas.drawRect(0, height - underLineHeight, tabsLayout.getWidth(), height, rectPaint);

        }
        if (isAllowDivider) {
            // draw divider

            dividerPaint.setColor(dividerColor);
            for (int i = 0; i < tabCount - 1; i++) {
                View tab = tabsLayout.getChildAt(i);
                canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding,
                        dividerPaint);
            }
        }
    }

    /**
     * ?
     */
    private ViewGroup getTabsLayout() {
        if (tabsLayout == null) {
            if (getChildCount() > 0) {
                tabsLayout = (ViewGroup) getChildAt(0);
            } else {
                removeAllViews();
                tabsLayout = new LinearLayout(getContext());
                addView(tabsLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT));
            }
        }
        return tabsLayout;
    }

    /**
     * ?Tab
     * @param position ?
     * @return TabView
     */
    public View getTab(int position) {
        if (tabsLayout != null && tabsLayout.getChildCount() > position) {
            return tabsLayout.getChildAt(position);
        } else {
            return null;
        }
    }

    /**
     * ?
     */
    private void scrollToChild(int position, int offset) {
        ViewGroup tabsLayout = getTabsLayout();
        if (tabsLayout != null && tabsLayout.getChildCount() > 0 && position < tabsLayout.getChildCount()) {
            View view = tabsLayout.getChildAt(position);
            if (view != null) {
                //X??
                int newScrollX = view.getLeft() + offset - getLeftMargin(view);
                if (position > 0 || offset > 0) {
                    newScrollX -= getWidth() / 2 - getOffset(view.getWidth()) / 2;
                }

                //?X???
                if (newScrollX != lastScrollX) {
                    lastScrollX = newScrollX;
                    scrollTo(newScrollX, 0);
                }
            }
        }
    }

    private int getLeftMargin(View view) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params instanceof MarginLayoutParams) {
            ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) params;
            return marginParams.leftMargin;
        }
        return 0;
    }

    private int getRightMargin(View view) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params instanceof MarginLayoutParams) {
            ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) params;
            return marginParams.rightMargin;
        }
        return 0;
    }

    /**
     * ????
     */
    private int getOffset(int newOffset) {
        if (lastOffset < newOffset) {
            if (start) {
                lastOffset += 1;
                return lastOffset;
            } else {
                start = true;
                lastOffset += 1;
                return lastOffset;
            }
        }
        if (lastOffset > newOffset) {
            if (start) {
                lastOffset -= 1;
                return lastOffset;
            } else {
                start = true;
                lastOffset -= 1;
                return lastOffset;
            }
        } else {
            start = true;
            lastOffset = newOffset;
            return lastOffset;
        }
    }

    /**
     * ?TAB
     */
    private void selectedTab(int currentSelectedTabPosition) {
        ViewGroup tabsLayout = getTabsLayout();
        if (currentSelectedTabPosition > -1 && tabsLayout != null
                && currentSelectedTabPosition < tabsLayout.getChildCount()) {
            if (currentSelectedTabView != null) {
                currentSelectedTabView.setSelected(false);
            }
            currentSelectedTabView = tabsLayout.getChildAt(currentSelectedTabPosition);
            if (currentSelectedTabView != null) {
                currentSelectedTabView.setSelected(true);
            }
        }
    }

    /**
     * Tab
     */
    public void addTab(View tabView, int index) {
        if (tabView != null) {
            getTabsLayout().addView(tabView, index);
            requestLayout();
        }
    }

    /**
     * Tab
     */
    public void addTab(View tabView) {
        addTab(tabView, -1);
    }

    /**
     * Tab
     * @param tabViews ?Tab
     */
    public void addTab(View... tabViews) {
        if (tabViews != null) {
            for (View view : tabViews) {
                getTabsLayout().addView(view);
            }
            requestLayout();
        }
    }

    /**
     * Tab
     */
    public void addTab(List<View> tabViews) {
        if (tabViews != null) {
            for (View view : tabViews) {
                getTabsLayout().addView(view);
            }
            requestLayout();
        }
    }

    /**
     * ViewPager
     * @param viewPager ViewPager
     */
    public void setViewPager(ViewPager viewPager) {
        if (disableViewPager)
            return;
        this.viewPager = viewPager;
        this.viewPager.setOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                selectedTab(position);
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageSelected(position);
                }
            }

            @Override
            public void onPageScrolled(int nextPagePosition, float positionOffset, int positionOffsetPixels) {
                ViewGroup tabsLayout = getTabsLayout();
                if (nextPagePosition < tabsLayout.getChildCount()) {
                    View view = tabsLayout.getChildAt(nextPagePosition);
                    if (view != null) {
                        currentPosition = nextPagePosition;
                        currentPositionOffset = positionOffset;
                        scrollToChild(nextPagePosition, (int) (positionOffset
                                * (view.getWidth() + getLeftMargin(view) + getRightMargin(view))));
                        invalidate();
                    }
                }
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageScrolled(nextPagePosition, positionOffset, positionOffsetPixels);
                }
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageScrollStateChanged(arg0);
                }
            }
        });
        requestLayout();
    }

    /**
     * Page??
     * @param onPageChangeListener Page??
     */
    public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
        this.onPageChangeListener = onPageChangeListener;
    }

    /**
     * ??
     * @param allowWidthFull true??Item?
     */
    public void setAllowWidthFull(boolean allowWidthFull) {
        this.allowWidthFull = allowWidthFull;
        requestLayout();
    }

    /**
     * ?
     */
    public void setSlidingBlockDrawable(Drawable slidingBlockDrawable) {
        this.slidingBlockDrawable = slidingBlockDrawable;
        requestLayout();
    }

    /**
     * ???
     * @param disableTensileSlidingBlock ???
     */
    public void setDisableTensileSlidingBlock(boolean disableTensileSlidingBlock) {
        this.disableTensileSlidingBlock = disableTensileSlidingBlock;
        invalidate();
    }

    /**
     * ?Tab
     */
    public int getTabCount() {
        ViewGroup tabsLayout = getTabsLayout();
        return tabsLayout != null ? tabsLayout.getChildCount() : 0;
    }

    /**
     * Tab?
     * @param onClickTabListener Tab?
     */
    public void setOnClickTabListener(OnClickTabListener onClickTabListener) {
        this.onClickTabListener = onClickTabListener;
    }

    /**
     * ?ViewPager
     * @param disableViewPager ?ViewPager
     */
    public void setDisableViewPager(boolean disableViewPager) {
        this.disableViewPager = disableViewPager;
        if (viewPager != null) {
            viewPager.setOnPageChangeListener(onPageChangeListener);
            viewPager = null;
        }
        requestLayout();
    }

    /**
     * Tab?
     */
    public interface OnClickTabListener {
        public void onClickTab(View tab, int index);
    }

    public int getBarColor() {
        return barColor;
    }

    public void setBarColor(int barColor) {
        this.barColor = barColor;
        this.invalidate();
    }

    public int getUnderlineColor() {
        return underlineColor;
    }

    public void setUnderlineColor(int underlineColor) {
        this.underlineColor = underlineColor;
        this.invalidate();
    }

    public int getBarHeight() {
        return barHeight;
    }

    public void setBarHeight(int barHeight) {
        this.barHeight = barHeight;
        this.invalidate();
    }

    public int getUnderLineHeight() {
        return underLineHeight;

    }

    public void setUnderLineHeight(int underLineHeight) {
        this.underLineHeight = underLineHeight;
        this.invalidate();
    }

    public void setAllowDivider(boolean isAllowDivider) {
        this.isAllowDivider = isAllowDivider;
    }

    public void setDividerColor(int dividerColor) {
        this.dividerColor = dividerColor;
    }

    public void setDividerPadding(int dividerPadding) {
        this.dividerPadding = dividerPadding;
    }

}