Viewpager 实现真正的无限滑动 Banner,拒绝 Integer.MAX_VALUE

7,131 阅读3分钟
原文链接: blog.csdn.net

Banner大家都不陌生,用于app首页轮播显示图片,并能无限轮播,这个效果一般有三种写法

  1. ViewPager设置Integer.MAX_VALUE,这也是大多数博客文章里的写法。
  2. 同样是使用ViewPager,但是getCount返回值不用为Integer.MAX_VALUE,只需返回图片数量+2

  3. 第三种就是自己自定义view了,这个好难,需要自己写滑动和手势速度判断,能写出来基本自定义view已经学的很6了。

这里我用的就是第二种方案,效果图如下:
这里写图片描述
上图可以看到,我一开始就是向左滑动的,显示的就是最后一张,一般采用MAX_VALUE写的话就是把当前item设置为MAX_VALUE的中间值来达到一开始就能向左滑动的目的,而且图中可以看到过程不存在卡顿,下面上代码主要实现方式,主要的实现方法都在adapter里面。

  private class BannerAdapter extends PagerAdapter  {

        private LayoutInflater mInflater;

        public BannerAdapter(Context context) {
            mInflater = LayoutInflater.from(context);
        }

        @Override
        public int getCount() {
            return ImageSize+2;
        }

        @Override
        public boolean isViewFromObject(View view, Object o) {
            return view == o;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            /**
             *    这个position是当前页面的下一个页面的缓存,若是想做滑动,position=当前item-1反之则加一
             *    举个例子这个viewpager总共包含了imagesize+2=7个页面
             *    positio=5时 position % ImageSize=0,切换到了第一个position
             */

            position %= ImageSize;
            View view = mInflater.inflate(R.layout.item, container, false);
            ImageView imageView = (ImageView) view.findViewById(R.id.meizi);
            TextView textView = (TextView) view.findViewById(R.id.name);
            imageView.setImageResource(mImagesSrc[position]);
            textView.setText(GRILS[position]);
            final int pos = position;
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(BannerActivity.this, "点击item :" + pos, Toast.LENGTH_SHORT).show();
                }
            });

            container.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            Log.d(TAG, "destroyItem%" + mBanner.getCurrentItem() + "sssss" + position);

            container.removeView((View) object);
        }

        @Override
        public void finishUpdate(ViewGroup container) {
            int position = mBanner.getCurrentItem();
            /**
             *  第五这里获得当前的positon然后对其setCurrentItem进行变换
             *  这里设置当position=0时把position设置为图片列表的最大值
             *  是为了position=0时左滑显示最后一张,我举个例子这里ImageSize是5
             *  当position==0时设置为5,左滑就是position=4,也就是第五张图片,
             *
             *  if (position == (ImageSize+2) - 1)
             *  这个判断 (ImageSize+2)这个是给viewpager设置的页面数,这里是7
             *  当position==7-1=6时,这时viewpager就滑到头了,所以把currentItem设置为1
             *  这里设置为1还是为了能够左滑,这时左滑position=0又执行了第一个判断又设置为5,
             *  这样就实现了无限轮播的效果
             *  setCurrentItem(position,false);
             *  这里第二个参数false是消除viewpager设置item时的滑动动画,不理解的去掉它运行下就知道啥意思了
             *
             */
            Log.i(TAG, "finishUpdate: "+position);
            if (position == 0) {
                position = ImageSize;
                mBanner.setCurrentItem(position,false);
            } else if (position == (ImageSize+2) - 1) {
                position = 1;
                mBanner.setCurrentItem(position,false);
            }
        }


    }

代码中包含的注释已经按我的理解写出来了,不知道讲的明不明白,下面我画几张图表示一下。
这里写图片描述

  • 这里就是一开始的跳转和当position滑到0的跳转,这里左滑时position=4就是显示的第五张图片(下标从0开始),这里如果一直左滑,滑到0时又重新设置就可以实现无限左滑.
    这里写图片描述
  • 当右滑时,滑到了6(这里是6,但是imagesize只有5怎么显示,这里你可以在instantiateItem方法中可以看到 position %= ImageSize; 从中可以看出5和6两个格子中加载的图片分别是第一张和第二张,当position=6时,viewpager到头了,所以跳转到position=1), 此时跳转到了position=1,此时左滑又继续上一步的跳转,所以我们继续右滑,滑到6时又跳转到1,所以右边也实现了无限滑动的目的。
  • 至此,两边都实现了真正的无限滑动,本篇没什么代码,基本就是上述那些
  • mBanner = (ViewPager) findViewById(R.id.banner);
    mBannerAdapter = new BannerAdapter(this);
    mBanner.setAdapter(mBannerAdapter);
    这样直接调用就可以,如果你需要加小圆点指示器之类,可以implements ViewPager.OnPageChangeListener 里面去获得position来设置,对了,自动滑动我偷懒就没写了,就是设置一个Timer使用就可以了,如果不会可以留言,我到时候给你写,如果什么时候有空就加上。