PagerSlidingTabStrip(更新中)

参考资料

  • [GitHub] Android PagerSlidingTabStrip
  • [codeKK] PagerSlidingTabStrip 源码解析
PagerSlidingTabStrip(更新中)_第1张图片
PagerSlidingTabStrip使用效果图

1. Usage

dependencies {
    compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
}

// Initialize the ViewPager and set an adapter
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new TestAdapter(getSupportFragmentManager()));

// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setViewPager(pager);
// continued from above
tabs.setOnPageChangeListener(mPageChangeListener);

2. 可自定义参数

  • pstsIndicatorColor: 滑动indicator的颜色
  • pstsIndicatorHeight: 滑动indicator的高度
  • pstsUnderlineColor: 底部分割线的颜色
  • pstsUnderlineHeight: 底部分割线的高度
  • pstsDividerColor: 两个tab之间分割线的颜色
  • pstsDividerPadding: 两个tab之间分割线的上下padding
  • pstsTabPaddingLeftRight: 每个tab的左右padding
  • pstsScrollOffset: Scroll offset of the selected tab
  • pstsTabBackground: Background drawable of each tab, should be a StateListDrawable
  • pstsShouldExpand: 设为true时,每个tab的weight相同,默认false
  • pstsTextAllCaps: 设为true时,所有tab标题为大写,默认true

3. 源码分析

PagerSlidingTabStrip(更新中)_第2张图片
PagerSlidingTabStrip类图

3.1 关联ViewPager

public void setViewPager(ViewPager pager) {
    this.pager = pager;

    if (pager.getAdapter() == null) {
        throw new IllegalStateException("ViewPager does not have adapter instance.");
    }

    pager.setOnPageChangeListener(pageListener);

    notifyDataSetChanged();
}
public void notifyDataSetChanged() {
    tabsContainer.removeAllViews();

    tabCount = pager.getAdapter().getCount();
    for (int i = 0; i < tabCount; i++) {
        if (pager.getAdapter() instanceof IconTabProvider) {
            addIconTab(i, ((IconTabProvider)pager.getAdapter()).getPageIconResId(i));
        } else {
            addTextTab(i, pager.getAdapter().getPageTitle(i).toString());
        }
    }

    updateTabStyles();

    getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @SuppressWarnings("deprecation")
        @SuppressLint("NewApi")
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }

            currentPosition = pager.getCurrentItem();
            scrollToChild(currentPosition, 0);
        }
    });
}

3.2 核心方法实现

private void scrollToChild(int position, int offset) {
    if (tabCount == 0) {
        return;
    }

    int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset;

    if (position > 0 || offset > 0) {
        newScrollX -= scrollOffset;
    }

    if (newScrollX != lastScrollX) {
        lastScrollX = newScrollX;
        scrollTo(newScrollX, 0);
    }
}
private class PageListener implements OnPageChangeListener {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        currentPosition = position;
        currentPositionOffset = positionOffset;

        scrollToChild(position, (int) (positionOffset * tabsContainer.getChildAt(position).getWidth()));

        //重新绘制
        invalidate();

        // 自定义ViewPager的OnPageChangeListener实现
        if (delegatePageListener != null) {
            delegatePageListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        // 滑动结束
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            scrollToChild(pager.getCurrentItem(), 0);
        }
        // 自定义ViewPager的OnPageChangeListener实现
        if (delegatePageListener != null) {
            delegatePageListener.onPageScrollStateChanged(state);
        }
    }

    @Override
    public void onPageSelected(int position) {
        // 自定义ViewPager的OnPageChangeListener实现
        if (delegatePageListener != null) {
            delegatePageListener.onPageSelected(position);
        }
    }
}

重写onDraw方法,对滑动indicator底部分割线tab之间的分割线进行绘制,实现了View的滑动。

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

    if (isInEditMode() || tabCount == 0) {
        return;
    }

    final int height = getHeight();
   
    // draw indicator line
    // 绘制滑动indicator
    rectPaint.setColor(indicatorColor);
   
    // default: line below current tab
    View currentTab = tabsContainer.getChildAt(currentPosition);
    float lineLeft = currentTab.getLeft();
    float lineRight = currentTab.getRight();

    // if there is an offset, start interpolating left and right coordinates between current and next tab
    if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {
        View nextTab = tabsContainer.getChildAt(currentPosition + 1);
        final float nextTabLeft = nextTab.getLeft();
        final float nextTabRight = nextTab.getRight();
        lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * lineLeft);
        lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight);
    }
    canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint);

    // draw underline
    // 绘制底部的分割线
    rectPaint.setColor(underlineColor);
    canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint);
   
    // draw divider
    // 绘制两个tab之间的分割线
    dividerPaint.setColor(dividerColor);
    for (int i = 0; i < tabCount - 1; i++) {
        View tab = tabsContainer.getChildAt(i);
        canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint);
    }
}

你可能感兴趣的:(PagerSlidingTabStrip(更新中))