实现自动播放的ViewPager

在App的开发过程中,经常会遇到活动页或头条内容自动播放的需求,为了快速解决此类问题,自定义了这个可自动播放的ViewPager, 开发过程中只需要简单的设置即可实现自动播放的功能。

循环播放

目前使用最普遍的方法就是重写ViewPager的Adapter时getCount()返回一个很大的数,使得ViewPager在切换时难以到达边界(最后一页),然后在instantiateItem()中通过取余的方式加载数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MyPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
if (mIsAutoPlay || mLoopPlay) {
return Integer.MAX_VALUE;
} else {
return mItemCount;
}
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
return listener.getView(container, position % mItemCount);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}

自动播放

在使用ViewPager的时候,一般我们都是通过侧滑来进行切换的。那么自动播放如何实现呢?其实很简单,我们知道ViewPager提供了setCurrentItem()来选择指定页,那么我们只需要通过Handler进行延迟操作即可实现。

1
2
3
4
5
6
7
8
9
10
11
... 
viewPager.setAdapter(new MyPagerAdapter());
// 延迟切换
handler.postDelayed(new Runnable() {
@Override
public void run() {
int index = viewPager.getCurrentItem();
index++;
viewPager.setCurrentItem(index);
}
}, mAutoSwitchTime);

这样ViewPager就可以自动播放了,但是这只是播放一次,我们知道,ViewPager切换后会回调onPageSelected()函数,那么我们只需要在此函数中延迟选择下一页即可实现完整的自动播放功能。

1
2
3
4
5
6
7
8
9
10
11
 @Override
public void onPageSelected(final int position) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
int index = viewPager.getCurrentItem();
index++;
viewPager.setCurrentItem(index);
}
}, mAutoSwitchTime);
}

切换动画

ViewPager提供了PageTransformer接口供开发者实现切换动画。开发者只需要实现transformPage方法,ViewPager在切换时即可使用自定义的动画效果。下面我们以滑动缩放为例来实现这个接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 @Override
public void transformPage(View page, float position) {
if (position >= -1 && position <= 0) { // 当前页面滑出屏幕(0-->-1)
float scaleRatio = (1 - mScale) * Math.abs(position);
page.setScaleX(1 - scaleRatio);
page.setScaleY(1 - scaleRatio);
float alpha = (1 - mAlpha) * Math.abs(position);
page.setAlpha(1 - alpha);
} else if (position > 0 && position <= 1) { // 新页面滑入(1-->0)
float scaleRatio = (1 - mScale) * (1 - position);
page.setScaleX(mScale + scaleRatio);
page.setScaleY(mScale + scaleRatio);
float alpha = (1 - mAlpha) * (1 - position);
page.setAlpha(mAlpha + alpha);
} else {
/**
* Nothing
*/

}
}

动画切换时间

ViewPager提供的这个实现切换动画的方式很方便,但却没有提供设置动画执行时间的方法,下面我们通过反射调用的方式来设置动画的执行时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 public void setDuration(int duration) {
try {
Field field = ViewPager.class.getDeclaredField("mScroller");
field.setAccessible(true);
MyScroller scroller = new MyScroller(viewPager.getContext(), new LinearInterpolator());
field.set(viewPager, scroller);
scroller.setDuration(duration);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}

public class MyScroller extends Scroller {

private int mDuration;

public MyScroller(Context context) {
super(context);
}

public MyScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}

@Override
public void startScroll(int startX, int startY, int dx, int dy) {
this.startScroll(startX, startY, dx, dy, mDuration);
}

@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, mDuration);
}

public void setDuration(int duration) {
this.mDuration = duration;
}
}

加载指示器

既然是自动播放控件,自然是少不了底部或顶部的指示器。其实这个没什么可说的,在setAdapter之后只加载一个LinearLayout并填充数据即可。

源码

至此,ViewPager自动播放的核心部分就已完成,具体的细节可参考源码。如有错误之处,欢迎指正!

,