Android 无限轮播ViewPager的实现

现在很多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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值