com.android.yijiang.kzx.widget.tab.PagerSlidingTabStrip.java Source code

Java tutorial

Introduction

Here is the source code for com.android.yijiang.kzx.widget.tab.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.android.yijiang.kzx.widget.tab;

import java.util.List;

import com.android.yijiang.kzx.R;

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

/**
 * ViewPager?
 * @version 1.1.1
 */
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 View currentSelectedTabView; //?
    private Drawable slidingBlockDrawable; //?
    private ViewPager viewPager; //ViewPager
    private ViewGroup tabsLayout; //
    private ViewPager.OnPageChangeListener onPageChangeListener; //???
    private OnClickTabListener onClickTabListener;

    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);
                attrsTypedArray.recycle();
            }
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        ViewGroup tabViewGroup = getTabsLayout();

        // 
        if (tabViewGroup == null || tabViewGroup.getChildCount() <= 0) {
            super.onLayout(changed, l, t, r, b);
            return;
        }

        int viewWidth = r - l;

        // Item
        if ((measure(tabViewGroup).getMeasuredWidth() < viewWidth) && allowWidthFull) {
            // ?tabViewGroup??
            viewWidth -= tabViewGroup.getPaddingLeft();
            viewWidth -= tabViewGroup.getPaddingRight();
            if (tabViewGroup.getLayoutParams() instanceof MarginLayoutParams) {
                MarginLayoutParams tabsLayoutParams = (MarginLayoutParams) tabViewGroup.getLayoutParams();
                viewWidth -= tabsLayoutParams.leftMargin;
                viewWidth -= tabsLayoutParams.rightMargin;
            }

            // ??Tab?
            View tabView;
            for (int w = 0; w < tabViewGroup.getChildCount(); w++) {
                tabView = tabViewGroup.getChildAt(w);
                if (tabView.getLayoutParams() instanceof MarginLayoutParams) {
                    MarginLayoutParams marginLayoutParams = (MarginLayoutParams) tabView.getLayoutParams();
                    viewWidth -= marginLayoutParams.leftMargin;
                    viewWidth -= marginLayoutParams.rightMargin;
                }
            }

            // ?
            int averageWidth = viewWidth / tabViewGroup.getChildCount();
            int bigTabCount = 0; // ?tab???
            for (int w = 0; w < tabViewGroup.getChildCount(); w++) {
                tabView = tabViewGroup.getChildAt(w);
                // ????
                if (tabView != null && tabView.getMeasuredWidth() > averageWidth) {
                    viewWidth -= tabView.getMeasuredWidth();
                    bigTabCount++;
                }
            }

            // ?
            averageWidth = viewWidth / (tabViewGroup.getChildCount() - bigTabCount);

            // ??Item
            for (int w = 0; w < tabViewGroup.getChildCount(); w++) {
                //?????
                tabView = tabViewGroup.getChildAt(w);
                if (tabView != null) {
                    ViewGroup.LayoutParams layoutParams = tabView.getLayoutParams();
                    if (layoutParams != null) {
                        layoutParams.width = tabView.getMeasuredWidth() < averageWidth ? averageWidth
                                : tabView.getMeasuredWidth();
                        tabView.setLayoutParams(layoutParams);
                        measure(tabView);
                    }
                }
            }
            measure(tabViewGroup);
        }

        // ?????
        currentPosition = viewPager != null ? viewPager.getCurrentItem() : 0;
        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);
        }

        super.onLayout(changed, l, t, r, b);
    }

    @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 (getTabsLayout() != null && getTabsLayout().getChildCount() > 0 && slidingBlockDrawable != null) {
            View currentTab = getTabsLayout().getChildAt(currentPosition);
            if (currentTab != null) {
                float slidingBlockLeft = currentTab.getLeft();
                float slidingBlockRight = currentTab.getRight();
                if (currentPositionOffset > 0f && currentPosition < getTabsLayout().getChildCount() - 1) {
                    View nextTab = getTabsLayout().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);
                    }
                }
                slidingBlockDrawable.setBounds((int) slidingBlockLeft, 0, (int) slidingBlockRight, getHeight());
                slidingBlockDrawable.draw(canvas);
            }
        }
    }

    /**
     * ?
     */
    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;
    }

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

                //?X???
                if (newScrollX != lastScrollX) {
                    lastScrollX = newScrollX;
                    scrollTo(newScrollX, 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;
        }
    }

    /**
     * ????ViewgetMeasuredXXX()????
     */
    private View measure(View view) {
        ViewGroup.LayoutParams p = view.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        view.measure(childWidthSpec, childHeightSpec);
        return view;
    }

    /**
     * ?TAB
     */
    private void selectedTab(int currentSelectedTabPosition) {
        if (currentSelectedTabPosition > -1 && getTabsLayout() != null
                && currentSelectedTabPosition < getTabsLayout().getChildCount()) {
            if (currentSelectedTabView != null) {
                currentSelectedTabView.setSelected(false);
            }
            currentSelectedTabView = getTabsLayout().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 && getTabsLayout() != null) {
            for (View view : tabViews) {
                getTabsLayout().addView(view);
            }
            requestLayout();
        }
    }

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

    /**
     * ViewPager
     * @param viewPager ViewPager
     */
    public void setViewPager(ViewPager viewPager) {
        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) {
                if (nextPagePosition < getTabsLayout().getChildCount()) {
                    View view = getTabsLayout().getChildAt(nextPagePosition);
                    if (view != null) {
                        currentPosition = nextPagePosition;
                        currentPositionOffset = positionOffset;
                        scrollToChild(nextPagePosition, (int) (positionOffset * view.getWidth()));
                        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();
    }

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

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

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