整理Viewpager无限轮播控件

一 自定义viewpagerAdapter
   1、最大值设置:getcount  返回 为Interger.MAXVALUE
   2、轮播之后View的移除  【防止重复添加view】

public class ImageAdapter extends PagerAdapter {
    private Context context;
    //轮播需要的图片
    public ArrayList<ImageView> imgs;

    public ImageAdapter(Context context, ArrayList<ImageView> imgs) {
        this.context = context;
        this.imgs = imgs;
    }

    /**
     * ViewPager的边界
     *
     * @return
     */
    @Override
    public int getCount() {
        //设置成最大,使无限循环
        return Integer.MAX_VALUE;
    }

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

    /**
     * 由于我们在instantiateItem()方法中已经处理了remove的逻辑,
     * 因此这里并不需要处理。实际上,实验表明这里如果加上了remove的调用,
     * 则会出现ViewPager的内容为空的情况。
     *
     * @param container
     * @param position
     * @param object
     */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        //警告:不要在这里调用removeView
    }

    /**
     * @param container
     * @param position
     * @return 对position进行求模操作
     * 因为当用户向左滑时position可能出现负值,所以必须进行处理
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        //对Viewpager页号求模去除View列表中要显示的项
        position %= imgs.size();
        if (position < 0) {
            position = imgs.size() + position;
        }
        ImageView view = imgs.get(position);
        //如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。

        ViewParent viewParent = view.getParent();
        if (viewParent != null) {
            ViewGroup parent = (ViewGroup) viewParent;
            parent.removeView(view);
        }
        container.addView(view);
        return view;
    }
}

二   handler 计时发消息设置 轮播currentItem

public class ImageHandler extends Handler {
    /**
     * 请求更新显示的View
     */
    public static final int MSG_UPDATE_IMAGE = 1;
    /**
     * 请求暂停轮播
     */
    public static final int MSG_KEEP_SILENT = 2;
    /**
     * 请求恢复轮播。
     */
    public static final int MSG_BREAK_SILENT = 3;
    /**
     * 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。
     * 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页,
     * 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。
     */
    public static final int MSG_PAGE_CHANGED = 4;
    //轮播间隔时间
    public static final long MSG_DELAY = 2000;

    //这里使用弱引用避免Handler泄露
    private WeakReference<MainActivity> weakReference;
    private int currentItem = Integer.MAX_VALUE / 2;

    public ImageHandler(WeakReference<MainActivity> wk) {
        weakReference = wk;
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        MainActivity mainActivity = weakReference.get();
        if (mainActivity == null) {
            //mainActivity已经回收,无需继续处理UI
            return;
        }
        //检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
        /**
         * 这段会把第一次的自动轮播事件吃掉,所以可以加个条件,Position!=Max/2的时候才清除事件.因为第一次Position一定等于Max/2
         */
        if ((mainActivity.mImageHandler.hasMessages(MSG_UPDATE_IMAGE)) && (currentItem != Integer.MAX_VALUE / 2)) {
            mainActivity.mImageHandler.removeMessages(MSG_UPDATE_IMAGE);
        }
        switch (msg.what) {
            case MSG_UPDATE_IMAGE:
                currentItem++;
                mainActivity.ChanggeViewPagerCurrentItem(currentItem);
                //准备下次播放
                mainActivity.mImageHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                break;
            case MSG_KEEP_SILENT:
                //只要不发送消息就暂停了
                break;
            case MSG_BREAK_SILENT:
                mainActivity.mImageHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                break;
            case MSG_PAGE_CHANGED:
                //记录当前的页号,避免播放的时候页面显示不正确。
                currentItem = msg.arg1;
                break;
            default:
                break;
        }
    }
}

三 在布局中 根据从服务器获取的image个数 决定 生成添加多少个圆点引导     根据MAX_VALUE/2  计算轮播起始是第一个的
position
public class MainActivity extends AppCompatActivity {
    private ViewPager vp;
    private ArrayList<ImageView> imageViews;
    private LinearLayout ll_icon_container;
    // 实际开发中这个数量是根据后台下发的图片个数  来决定创建多少个小圆点
    private int imageCount = 15;
    public ImageHandler mImageHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initVIew();
        initListener();
    }

    private void initVIew() {
        vp = (ViewPager) findViewById(R.id.main_picturecarousel_vp);
        ll_icon_container = findViewById(R.id.ll_icon_container);
        imageViews = new ArrayList<>();
        LayoutInflater inflater = LayoutInflater.from(this);
        ll_icon_container.removeAllViews();
        for (int i = 0; i < imageCount; i++) {
            ImageView imgv = (ImageView) inflater.inflate(R.layout.image_item, null);
            imgv.setImageResource(R.mipmap.ic_launcher);
            imageViews.add(imgv);
            //初始化原点点
            ImageView icon = (ImageView) inflater.inflate(R.layout.icon_view, null);
            ll_icon_container.addView(icon);
        }
        vp.setAdapter(new ImageAdapter(MainActivity.this, imageViews));
        mImageHandler = new ImageHandler(new WeakReference<>(this));


    }

    private void initListener() {
        vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                retSetIcon(position);
                mImageHandler.sendMessage(Message.obtain(mImageHandler, ImageHandler.MSG_PAGE_CHANGED, position, 0));
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                switch (state) {
                    case ViewPager.SCROLL_STATE_DRAGGING:
                        mImageHandler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT);
                        break;
                    case ViewPager.SCROLL_STATE_IDLE:
                        mImageHandler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
                        break;
                    default:
                        break;
                }
            }
        });

        setFirstIndex();
        //开始轮播效果
        mImageHandler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
    }

    /**
     * 设置第一个图片的下标
     */
    private void setFirstIndex(int count) {
  for (int i = 250; i < 500; i++) {
    if (i % count == 0) {
      mViewPager.setCurrentItem(i);
      Log.e("flag","------------------拿到的数字为:"+i);
      break;
    }
  }
}
    /**
     * 更新小圆点状态
     *
     * @param position
     */
    private void retSetIcon(int position) {
        for (int i = 0; i < ll_icon_container.getChildCount(); i++) {
            ((ImageView) ll_icon_container.getChildAt(i)).setImageResource(R.mipmap.select_no);
        }
        ((ImageView) ll_icon_container.getChildAt(position % imageCount)).setImageResource(R.mipmap.select_icon);
    }

    /**
     * 轮播时设置当前的条目
     *
     * @param position
     */
    public void ChanggeViewPagerCurrentItem(int position) {
        vp.setCurrentItem(position);
        retSetIcon(position);
    }
}
demo地址为https://download.csdn.net/download/xuwb123xuwb/10327452

猜你喜欢

转载自blog.csdn.net/xuwb123xuwb/article/details/79818215