AutoScrollViewPager与PageIndicator无限循环混合使用

本文介绍如何在Android应用中实现无限循环的广告轮播功能,并使其与指示器兼容。通过改造AutoScrollViewPager与ViewPagerIndicator,解决了无限循环时指示器假死的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目需要加入广告轮播功能,就小学习了一下,发现 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就可以兼容使用了.

附上demo 

其实实现方法有很多,不过大概思路都差不多。我是发现AutoScrollViewPager中的对页面回收写的不错,性能不错,所以在其之上改写了一下。




评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值