本来也没想过发博客,但是随着碎片化的东西越来越多,很多以前扒过的东西在很长一段时间不用之后再回头又得再扒一遍,所以还是整理一下方便以后再遇到此类问题直接回来看自己博客,能更快的解决问题。
今天刚好在写一个viewpager无限循环的需求,这个点之前特地研究过网络上现存的几种方案,比较之后还是觉得将adapter的count值设置成最大,最为方便,效果也是最好。理由后面再说,先上代码:
public class ViewPagerAdapter extends PagerAdapter {
private Context context;
private List<String> urls;
private List<ImageView> imgs = new ArrayList<>();
private View view;
public ViewPagerAdapter(Context context, List<String> urls) {
this.context = context;
this.urls = urls;
for (String str :
urls) {
ImageView img = new ImageView(context);
Glide.with(context).load(str).into(img);
imgs.add(img);
}
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
view = imgs.get(position % imgs.size());
if (view.getParent() != null) {
container.removeView(view);
}
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//由于在instantiateItem方法里已经实现了自行销毁所以这里可以什么都不做
}
}
对于这种方案,我见过的评论最多的是,会一下子初始化很多个实例,会影响性能。但是从
@Override
public Object instantiateItem(ViewGroup container, int position) {
view = imgs.get(position % imgs.size());
if (view.getParent() != null) {
container.removeView(view);
}
container.addView(view);
return view;
}
可以发现,container是在一边添加的时候一边在删除实例,container内部存贮的实例最多不超过urls集合的长度,而一般我们循环的viewpager的内容也就几个。这点开销我并不认为会对APP的体验照常多大的影响,所以值得推荐。
方案二,是通过OnPageChangeListener接口的onPageScrollStateChanged方法来实现,代码如下:
boolean isLast = false;
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == 2) {
isLast = false;
} else if (state == 0 && isLast) {
// 当前页数大于1则是最后一页
if (pager.getCurrentItem() >= 1) {
pager.setCurrentItem(0);
} else {
pager.setCurrentItem(models.size() - 1);
}
} else {
isLast = true;
}
}
});
这里的state 取值范围为 0、1、2对应为
0~什么都没做
1~开始滑动
2~滑动结束
这段代码的效果是,当你从在第一页左划时,他回快速的的弹到最后一页,从最有一页往右划时他回快速的会到起点,并且其并不会相应手指的移动事件,只是在停止移动式,快速的滚动,虽然达到了无限循环的功能,但是效果不佳。当然可以禁掉动画,那样画面仍然会闪一下。
方案三,也是搜viewpager无限循环出现结果最多的一种方法(这里就不帖代码了,只评论),即再pager开始合结束的后面再加上一页,本来是 1、2、3、4 的排序增加变成4、1、2、3、4、1,这比方案二好的是在原本的 1 和4的时候 继续左划和右划会出现相应时间了,但是当你从1->4或者从4->1时 由于这里会重新设置一下setCurrentItem,所以不可避免的画面还是要闪一下,当然体验上来说比方案二好了很多。
综上,如果在性能影响微乎其微,但是效果更佳完美的话,相信很多人都会跟我选择一样的方案一。
最后再记录一下,今天使用方案一结合viewpageindicator居然出现了卡死现象,但是回头一想也就释然了,viewpageindicator是根据pager的count来计算点的,你一个无限大他要画那么多个点,换谁谁都得死,目前还没有找到解决这个问题的方案,所以解决方案是自己去用linearlayout实现效果。