void onPageSelected(int position)
? ?{
? ? // 设置字体颜色高亮
? ? resetTextViewColor();
? ? highLightTextView(position);
? ? // 回调
? ? if (onPageChangeListener != null)
? ? {
? ? ?onPageChangeListener.onPageSelected(position);
? ? }
? ?}
? ?@Override
? ?public void onPageScrolled(int position, float positionOffset,
? ? ?int positionOffsetPixels)
? ?{
? ? // 滚动
? ? scroll(position, positionOffset);
? ? // 回调
? ? if (onPageChangeListener != null)
? ? {
? ? ?onPageChangeListener.onPageScrolled(position,
? ? ? ?positionOffset, positionOffsetPixels);
? ? }
? ?}
? ?@Override
? ?public void onPageScrollStateChanged(int state)
? ?{
? ? // 回调
? ? if (onPageChangeListener != null)
? ? {
? ? ?onPageChangeListener.onPageScrollStateChanged(state);
? ? }
? ?}
? });
? // 设置当前页
? mViewPager.setCurrentItem(pos);
? // 高亮
? highLightTextView(pos);
?}
很简单的代码,我们关联上ViewPager以后,立刻注册setOnPageChangeListener,关于指示器的跟随移动,核心代码是:onPageScrolled中的
// 滚动
scroll(position, positionOffset);这行后面介绍~
这里注意下,我们不是把setOnPageChangeListener用了么,但是用户可能也需要监听这个接口,去干一些事,那么我们就需要给用户解决,于是我们自己定义一个类似的接口公布给用户:
/**
? * 对外的ViewPager的回调接口
? *
? * @author zhy
? *
? */
?public interface PageChangeListener
?{
? public void onPageScrolled(int position, float positionOffset,
? ? int positionOffsetPixels);
? public void onPageSelected(int position);
? public void onPageScrollStateChanged(int state);
?}
?// 对外的ViewPager的回调接口
?private PageChangeListener onPageChangeListener;
?// 对外的ViewPager的回调接口的设置
?public void setOnPageChangeListener(PageChangeListener pageChangeListener)
?{
? this.onPageChangeListener = pageChangeListener;
?}
如果用户需要回调,请使用我们的mIndicator.setOnPageChangeListener,回调的方法和原本的listener一模一样~~?
ps:不要问我,这里用了mViewPager.setOnPageChangeListener我还想监听咋办,以及我设置了mViewPager.setOnPageChangeListener指示器怎么不动了,请仔细看上文
当然了,还有个高亮文本和重置文本颜色的代码,其实就是简单改变下当前选择的Tab的文本的颜色。
/**
? * 高亮文本
? *
? * @param position
? */
?protected void highLightTextView(int position)
?{
? View view = getChildAt(position);
? if (view instanceof TextView)
? {
? ?((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHTCOLOR);
? }
?}
?/**
? * 重置文本颜色
? */
?private void resetTextViewColor()
?{
? for (int i = 0; i < getChildCount(); i++)
? {
? ?View view = getChildAt(i);
? ?if (view instanceof TextView)
? ?{
? ? ((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
? ?}
? }
?}
接下来就到scroll登场了~?
/**
? * 指示器跟随手指滚动,以及容器滚动
? *
? * @param position
? * @param offset
? */
?public void scroll(int position, float offset)
?{
? /**
? *
? *? 0-1:position=0 ;1-0:postion=0;
? *
? */
? // 不断改变偏移量,invalidate
? mTranslationX = getWidth() / mTabVisibleCount * (position + offset);
? int tabWidth = getScreenWidth() / mTabVisibleCount;
? // 容器滚动,当移动到倒数最后一个的时候,开始滚动
? if (offset > 0 && position >= (mTabVisibleCount - 2)
? ? && getChildCount() > mTabVisibleCount)
? {
? ?if (mTabVisibleCount != 1)
? ?{
? ? this.scrollTo((position - (mTabVisibleCount - 2)) * tabWidth
? ? ? + (int) (tabWidth * offset), 0);
? ?} else
? ?// 为count为1时 的特殊处理
? ?{
? ? this.scrollTo(
? ? ? position * tabWidth + (int) (tabWidth * offset), 0);
? ?}
? }
? invalidate();
?}
看完之后,有没有一种,卧槽,就这几行代码就实现了,指示器跟随滚动和我们的Tab跟随滚动~~
?
嗯,其实指示器跟随滚动上面说了,依赖mTranslationX,然后借着canvas.translate实现的~~也就是说,就一行去确定当前应该的偏移即可。
比如:从第0个Tab滑向第1个Tab:position为0,offset会0.0~1.0这么变化~我们的偏移量实际也就是增加?offset * 每个Tab的宽度~
好了,下面说容器滚动,其实容器滚动的x也是?offset * 每个Tab的宽度~;只不过,有个前提就是当前滑动的是可见的倒数第二个到最后一个,所以我们有个判断:
?position >= (mTabVisibleCount - 2) ; 于是乎,我们在偏移的时候也有:(position - (mTabVisibleCount - 2)) * tabWidth ;如当前恰好是可见的倒