Android小坑Android开发经验谈Android开发

viewpager的循环滑动和图片轮播

2017-08-09  本文已影响68人  badc59a1a8c4

今天下午结束了,重新加载网络页面的优化。并完成了viewpager的循环滑动和图片轮播。感触颇深啊,刚开始提手的时候发现我连viewpager怎么都忘记了。

图片的轮播和循环滑动两个功能结合在一起的话,我认为,还是用viewpager最为简单。有查资料,现在主流的方式主要是两种, 一种是在list<View>的头和尾个添加一个元素如:list<View>-->1,2,3那么添加完了以后的结果是:list<view>-->3,1,2,3,1。但是显示的是原来的三个元素。通过onPagerChangeListener中的onPageSelected方法设定:(以三个元素为例)在viewpager的位置小于1的时候,3,在大于3的时候则直接跳到1(这里的位置都是包括0的)。由此来实现循环滑动。

但是这种方法有一个缺陷,就是在一组数据滑完,进入另一组数据进行切换的时候,会有明显的不自然的感觉。

因此,基于良好的用户体验,我选择了第二种。而第二种方法是通过将循环的数目增到最大:

  @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

通过 return views.get(position % views.size());来确定viewpager的位置,但是这样也是有缺陷的。首先它不是真正意义上的无限循环,只不过是有很大的边界而已。其次,当页面的总数是2和3的时候,就不能销毁复用的页面,否者会出现错误,程序报错说是,在添加新的页面之前没有将之前的页面销毁掉。研究一下发现viewpager一般会缓存两个数据,而2和3刚好在这两个缓存的数据之间。要修改这个bug的话就要重写viewpager类,显然,这样做很麻烦,也费时费力所以我设置了一个判断来解决这个问题。接下来上整个pagerAdapter的代码和setadapter的代码。
ViewpagerAdapter 代码:

    public class ViewpagerAdapter extends PagerAdapter {
    private Context mContext;
    private List<View> views;

    public ViewpagerAdapter(Context mContext, List<View> views) {
        this.mContext = mContext;
        this.views = views;

    }

    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if(views.size()>3){
            ((ViewPager)container).removeView(views.get(position % views.size()));
        }

    }
    /**
     * 载入图片进去,用当前的position 除以 图片数组长度取余数是关键
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        try {
            ((ViewPager)container).addView(views.get(position % views.size()), 0);
        }catch(Exception e){
            //handler something
        }
        return views.get(position % views.size());
    }
}

setadapter代码

 int[] imageIds = {R.mipmap.btn1,R.mipmap.btn12,R.mipmap.btn3};
        final List<View> views = new ArrayList<>();
        for (int i = 0; i <imageIds.length ; i++) {
            ImageView imageView = new ImageView(getActivity());
            imageView.setBackgroundResource(imageIds[i]);
            views.add(imageView);
        }
        viewpagerAdapter = new ViewpagerAdapter(getActivity(),views);
        viewPager.setAdapter(viewpagerAdapter);
        viewPager.setCurrentItem((views.size()) * 1000);

接下来是响应每个图片的点击事件是通过获取每个图片所在的imageView的实例,然后用for来判断点击的:

        /**
         * 设置viewpager的点击事件
         */
        for (int i = 0; i <views.size() ; i++) {
            views.get(i).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(getActivity(),"选的的数字"+viewPager.getCurrentItem(),Toast.LENGTH_SHORT).show();
                }
            });
        }

最后就是图片的轮播了,如果单单只有轮播就很简单了,循环一个延时的线程就可以了,但是我们滑动viewpager的时候,肯定是不想让它自动跳转了,所以我们判断当前的viewpager页面的状态:onPagerChageListener的onPageScrollStateChanged(int state)的参数:0---》表示没有动作,1---》表示正在滑动,2---》表示滑动结束,通过监听状态,设置标签,当标签为true时,就开始循环,当为false的时候,线程就不执行循环操作,
下面是代码:

     viewPager.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==0){
                    pagerFlag = true;
                }else {
                    pagerFlag = false;
                }

            }
        });

循环线程代码:

  final Handler handler = new Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                if(pagerFlag){
                    viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
                }
                Log.d(TAG, "run: "+"图片标记"+pagerFlag);
                handler.postDelayed(this,5000);
            }
        });

好了,今天就这些了,明天是动态添加上传大量图片。敬请期待
---2016-07-14

上一篇下一篇

猜你喜欢

热点阅读