首页 > 系统 > Android > 正文

Android 无限轮播ViewPager的实现

2019-11-09 18:37:17
字体:
来源:转载
供稿:网友

现在很多app的首页顶部都有一个可以滑动切换的ViewPager,或是显示广告图片,或是显示入口推荐信息等等。很多这些ViewPager都带有无限滑动的功能,也就是当滑动到最后一张图片时,继续向右滑动会转到第一张图片;当在第一张图片向左滑动时,会转到最后一张图片。这种功能的实现提升了用户的体验,使用户能更方便的切换,而不用每次都要滑动N次来导航到第一张或是最后一张图片。这种功能的实现很简单,可以通过一些小技巧来实现。下面看看实现后的效果图: 这里写图片描述

主要的思路:假设现在ViewPager中有5个ImageView的Item,分别编号1,2,3,4,5。然后在第一个元素之前加一个编号5的Item,在最后一个元素之后加一个编号1的Item。现在ViewPager中有7个Item,分别为5,1,2,3,4,5,1。如图所示: 这里写图片描述

现在有两个场景需要来进行分析。首先假设第二个元素1为当前Item,当在第二个元素1的Item向左滑动时,就到了第一个元素5的Item,当没有进行任何处理时,继续向左滑动是没效果的。我们可以利用ViewPager的setCurrentItem的方法,当从第二个元素1的Item滑动到第一个元素5的Item位置时,就调用setCurrentItem方法使ViewPager跳转到第六个元素5的Item位置处,然后继续向左滑动就从元素5到元素4到元素3了,这样就可以无限向左滑动了。

这里写图片描述

第二个场景是无限右滑了。首先假设第六个元素5为当前Item,当向右滑动时,就到了第七个元素也就是最后一个元素1的Item了。此时如果没有任何处理,当继续向右滑动时时没有任何效果的。所以当到了第七个元素1的时候,我们就调用ViewPager的setCurrentItem方法跳转到第二个元素1的Item位置,然后继续向右滑动就到了元素2到元素3了,这样就可以无限向右滑动了。

这里写图片描述

其实无限向右滑动和向左滑动都是一种障眼法的实现。现在来看看ViewPager提供的setCurrentItem方法。setCurrentItem方法有两个参数,第一个参数是跳转到第几个item,第二个参数是否开启当跳转的时候慢慢滑动过去,设置为false就完全感觉不到跳转的影子了,障眼法就是这样实现的,如果设置为true,你就会看到一次跳转中间很多Item的效果了。如GIF图显示:

public void setCurrentItem(int item, boolean smoothScroll) { mPopulatePending = false; setCurrentItemInternal(item, smoothScroll, false);}

这里写图片描述

最后还有一个就是对ViewPager进行监听了,当从第二个元素1向左滑动到第一个元素5和从倒数第二个元素5向右滑动到倒数第一个元素1的时候进行处理。监听ViewPager主要是利用了OnPageChangeListener。OnPageChangeListener里面有3个需要重写的方法,我们主要利用onPageSelected和onPageScrollStateChanged。onPageSelected在onPageScrollStateChanged之前先被调用,所以在onPageSelected中判断当前位置,并进行处理,设置当前位置值。在onPageScrollStateChanged中调用setCurrentItem方法跳转到当前位置值。

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if(position>LAST_ITEM_INDEX){ isChanged=true; currentPos=FIRST_ITEM_INDEX; }else if(position<FIRST_ITEM_INDEX){ isChanged=true; currentPos=LAST_ITEM_INDEX; } } @Override public void onPageScrollStateChanged(int state) { if(ViewPager.SCROLL_STATE_IDLE==state){ if(isChanged){ isChanged=false; viewPager.setCurrentItem(currentPos,false); } } } }); }

注意必须设置FIRST_ITEM_INDEX为第二个元素1的位置,即1。LAST_ITEM_INDEX为倒数第二个元素5的位置,即images.size()-2;,就是你的源数组倒数第二个元素的位置。isChanged是用来判断当前是否需要跨越中间多个item进行跳转,也就是上面所说的技巧了。

完整代码:

public class MainActivity extends BaseActivity { PRivate ViewPager viewPager; private ImageAdapter imageAdapter; private int FIRST_ITEM_INDEX; private int LAST_ITEM_INDEX; private int currentPos; private boolean isChanged; @Override protected void initView() { setContentView(R.layout.activity_main); viewPager= (ViewPager) findViewById(R.id.MainActivity_ViewPager); } @Override protected void initData() { int[] resIds=new int[]{R.drawable.img_one,R.drawable.img_two,R.drawable.img_three,R.drawable.img_four,R.drawable.img_five}; ArrayList<ImageView> images=new ArrayList<>(); initImages(images,resIds); imageAdapter=new ImageAdapter(this,images); viewPager.setAdapter(imageAdapter); viewPager.setCurrentItem(1); FIRST_ITEM_INDEX=1; LAST_ITEM_INDEX=images.size()-2; } @Override protected void initListener() { viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if(position>LAST_ITEM_INDEX){ isChanged=true; currentPos=FIRST_ITEM_INDEX; }else if(position<FIRST_ITEM_INDEX){ isChanged=true; currentPos=LAST_ITEM_INDEX; } } @Override public void onPageScrollStateChanged(int state) { if(ViewPager.SCROLL_STATE_IDLE==state){ if(isChanged){ isChanged=false; viewPager.setCurrentItem(currentPos,false); } } } }); } private void initImages(ArrayList<ImageView> images,int[] resIds){ images.add(createImage(resIds[resIds.length-1])); for(int i=0;i<resIds.length;i++){ images.add(createImage(resIds[i])); } images.add(createImage(resIds[0])); } private ImageView createImage(int resId){ ImageView img=new ImageView(this); img.setScaleType(ImageView.ScaleType.CENTER_CROP); Glide.with(this) .load(resId) .dontAnimate() .into(img); return img; }}

PagerAdapter实现:

public class ImageAdapter extends PagerAdapter { private List<ImageView> images; private Context context; public ImageAdapter(Context context, ArrayList<ImageView> images){ this.context=context; this.images=images; } @Override public int getCount() { return images.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } @Override public void destroyItem(ViewGroup container,int position,Object object){ container.removeView(images.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position){ View view=images.get(position); final int pos=position; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, String.valueOf(pos), Toast.LENGTH_SHORT).show(); } }); ViewPager viewPager= (ViewPager) container; viewPager.addView(view); return images.get(position); }}

github地址: https://github.com/QQ402164452/LoopViewPagerDemo


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表