最近项目需要加入广告轮播功能,就小学习了一下,发现 Trinea的Android Auto Scroll ViewPager还不错,附链接点击打开链接,效果与性能都还不错,还可以无限循环轮播。
一般轮播都会和指示器配合使用,我使用的ViewPagerIndicator,结果无限循环这个特性不能和 ViewPagerIndicator 使用,所以准备写一个兼容版的。
这个兼容问题的主要原因是,ViewPager如果开启无限循环功能,会有很多页(Integer.MAX_VALUE个,不明白的可以脑补一下代码),而ViewPagerIndicator需要绘制指示点,不修改代码的话就要绘制Integer.MAX_VALUE个点,所以就直接假死了。
解决办法就是,让ViewPagerIndicator取得的项数为实际值,让AutoScrollViewPager取得的项数为虚拟很大的值。
这里可以运用装饰模式,代码如下,这是原始的的Adapter,树getCount()返回实际的值
public class AdvertImagePagerAdapter extends RecyclingPagerAdapter {
private Context context;
private List<Integer> imageIdList;
private int size;
private boolean isInfiniteLoop;
public AdvertImagePagerAdapter(Context context, List<Integer> imageIdList) {
this.context = context;
this.imageIdList = imageIdList;
this.size = imageIdList.size();
isInfiniteLoop = false;
}
@Override
public int getCount() {
// Infinite loop
return isInfiniteLoop ? Integer.MAX_VALUE : imageIdList.size();
}
/**
* get really position
*
* @param position
* @return
*/
private int getPosition(int position) {
return position % size;
}
@Override
public View getView(int position, View view, ViewGroup container) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = holder.imageView = new ImageView(context);
holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.imageView.setImageResource(imageIdList.get(getPosition(position)));
return view;
}
private static class ViewHolder {
ImageView imageView;
}
/**
* @return the isInfiniteLoop
*/
public boolean isInfiniteLoop() {
return isInfiniteLoop;
}
/**
* @param isInfiniteLoop the isInfiniteLoop to set
*/
public AdvertImagePagerAdapter setInfiniteLoop(boolean isInfiniteLoop) {
this.isInfiniteLoop = isInfiniteLoop;
return this;
}
}
装饰后的Adapter,getCount()返回一个很大的值,代码如下
public class AdvertImagePagerAdapterDecorator extends RecyclingPagerAdapter {
private AdvertImagePagerAdapter adapter;
public AdvertImagePagerAdapterDecorator(AdvertImagePagerAdapter adapter) {
this.adapter = adapter;
}
@Override
public View getView(int position, View convertView, ViewGroup container) {
return adapter.getView(position, convertView, container);
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
}
为了让装饰后的Adapter发挥作用,还需修改AutoScrollViewPager,需重写setAdapter()与getAdapter(),代码如下:
private PagerAdapter advertPagerAdapter;
@Override
public void setAdapter(PagerAdapter advertPagerAdapter) {
this.advertPagerAdapter = advertPagerAdapter;
super.setAdapter(new AdvertImagePagerAdapterDecorator((AdvertImagePagerAdapter) advertPagerAdapter));
}
@Override
public PagerAdapter getAdapter() {
return advertPagerAdapter;
}
ViewPagerIndicator并不适合无限循环,所以也需要改写一下,首先是OnDraw(),其中的
if (mCurrentPage >= count) {
setCurrentItem(count - 1);
return;
}
表示到最后一项后,跳转到第一项,这里是无限循环,所以将其注释掉,接下来是onPageScrolled()
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position!=mCurrentPage) {
mCurrentPage = position;
mPageOffset = 0;
invalidate();
}
if (mListener != null) {
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
其中的mPageOffset,指示器移动时的偏移量,这里对我们无用,直接赋值0.
这样AutoScrollViewPager与PageIndicator就可以兼容使用了.
其实实现方法有很多,不过大概思路都差不多。我是发现AutoScrollViewPager中的对页面回收写的不错,性能不错,所以在其之上改写了一下。