Android ViewPager的无限循环与自动滚动实现

Android ViewPager的无限循环与自动滚动实现

前言

关于ViewPager时Android开发时经常要用到的控件,但系统提供的ViewPager往往总有一些功能限制,如不能无限循环,不能自动滚动,今天就介绍ViewPager无限循环和自动滚动的不同实现。

实现思路

实现方式有很多种,具体如下,后面会分析各种实现方式的优缺点。

无限循环方式

更改Adapter实现方式

即getCount返回Integer.MAX_VALUE

核心代码(这种方式其实是一种伪无限循环):

private MyPageAdapter extends PageAdapter {
    @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
}
处理数据源

即让ViewPager绑定的数据源模拟出一个循环效果即可,真实数据源唯0123,将其变为301230);

核心代码:

// 绑定到ViewPager的数据源
private List<T> datas = new ArrayList<>();
// 真实数据源
private List<T> realDatas = new ArrayList<>();
// handler
private Handler handler = new Handler();
// 要无限循环的ViewPager
private void initDatas() {
    // 先加入真实数据的最后一个
    datas.add(realDatas.get(realDatas.size() - 1));
    for(T t : realDatas) {
        datas.add(T);
    }
    // 最后加入真实数据第一个
    datas.add(realDatas.get(0));

    // 绑定数据的操作
    ...
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset,
                                       int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(final int position) {
                if(position == 0 || position == datas.size() -1) {
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            viewPager.setCurrentItem(Math.abs(datas.size() - position -2), false);
                        }
                    })
                }

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });


}
从OnPageChangeListener入手

当滑动到临界值时,主动调用ViewPager的setCurrentItem方法;

具体实现思路如下(只是我的思路尚未代码验证):

// 数据源
private List<T> datas;
// 要无限循环的ViewPager
private ViewPager viewPager;
// 上次展示的页面
private int lastItem;
// 当前ViewPager展示页
private int currentItem;
// 是否正在向左滑
private boolean isDraggingToLeft = false;
// handler
private Handler handler = new Handler();
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset,
                                       int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                lastItem = currentItem;
                currentItem = position;

            }

            @Override
            public void onPageScrollStateChanged(int state) {
                switch (state) {
                    case ViewPager.SCROLL_STATE_DRAGGING:

                        break;
                    case ViewPager.SCROLL_STATE_SETTLING:

                        break;
                    case ViewPager.SCROLL_STATE_IDLE:
                        if (lastItem > currentItem) {
                            isDraggingToLeft = true;
                        }
                        if (isDraggingToLeft) {//左滑滑到0
                            if (currentItem == 0) {
                                currentItem = datas.size() - 1;
                            }
                        } else {//右滑滑到datas.size() -1
                            if (currentItem == datas.size() - 1) {
                                currentItem = 0;
                            }
                        }
                        // 展示一段时间,在通过ViewPager的setCurrentItem来设置到第0页
                        // sleep(bannerShowTime),这里只是模拟,可以用handler实现
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                viewPager.setCurrentItem(currentItem);
                            }
                        }, 200);
                        break;
                }

            }
        });

不足之处:

采用方法1时,当调用ViewPager的setCurrentItem方法时会造成ANR(只有在onCreate中调用不回出现),解决方法,可设置一个比较大的值,而不采用Integer.MAX_VALUE;

采用方法2和3时,

  • 需要解决最后一个到第一个的闪屏问题,我的思路是采用handler来延时处理;
  • 需要解决手动滑动时如何处理

自动滚动实现方式

自动滚动逻辑功能要求
  1. 手动滚动开始时,自动滚动暂停;
  2. 手动滚动结束时,自动滚动开始;

上面两个是通用处理,也就是说,不管哪种实现方式,都要考虑。

自动滚动实现方式
  1. 利用Handler来实现自动滚动

    代码实现如下(核心代码如下):

    // 要自动滚动的ViewPager
    private ViewPager viewPager;
    // 定义是否开启自动滚动,默认开启
    private boolean isAutoPlay = true;
    // 默认自动滚动任务延时两秒执行
    private int delayTime = 2000;
    // 定义处理自动滚动的handler
    private Handler handler = new Handler();
    // 当前ViewPager展示页
    private int currentItem;
    
    /**
    *   开启自动滚动的方法
    */
    private void startAutoPlay() {
    isAutoPlay = true;
    handler.removeCallbacks(task);
    handler.postDelayed(task, delayTime)
    }
    
    /**
    * 暂停自动滚动
    */
    public pauseAutoPlay() {
       isAutoPlay = false;
    handler.removeCallbacks(task);
    }
    /**
    * 自动滚动核心代码
    */
    private final Runnable task = new Runnable() {
    @Override
        public void run() {
        if (isAutoPlay) {
             // 自动滚动逻辑处理
            currentItem = viewPager.getCurrentItem();
                currentItem++;
               if(currentItem == randyPagerAdapter.getCount() -1) {
                currentItem = 0;
                viewPager.setCurrentItem(currentItem);
                    handler.postDelayed(this, delayTime);
               } else {
                   viewPager.setCurrentItem(currentItem);
                   handler.postDelayed(this, delayTime);    
               }
           } else {
               handler.postDelayed(this, delayTime);
           }
        }
    };
    

  2. 利用定时任务(Timer和TimerTask)来实现

    代码实现(核心代码如下):

    private static final int DISPLAY_TIME = 3000;
    private Handler hander = new Handler();
    private Timer timer = new Timer();
    private TimerTask timerTask;
    private ViewPager mViewPager;
    private Runnable runable = new Runnable() {
       @Override
       public void run() {
           //true表示平滑滚动
           mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1, true);
       }
    };
    public void startScroll() {
       timerTask = new TimerTask() {
           @Override
           public void run() {
               hander.post(runable);
           }
       };
       timer.schedule(timerTask, DISPLAY_TIME, DISPLAY_TIME);
    }
    public void stopScroll() {
       timerTask.cancel();
       timerTask = null;
    }

    总结

    • 在处理无限循环时,核心思路就是对临界值的处理,当然也可以通过方法1来绕过这种处理,但要注意一点就是怎么设置getCount的返回值以达到最优的性能;
    • 在处理自动滚动时,无非就是通过handler的postDelayed方法的特性以及Android定义的定时器进行处理。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android横向无限循环滚动组件通常是指可以在横向方向上无限循环滚动的控件,常见的例子是轮播图组件。使用这样的组件可以实现在一组图片或其他视图之间平滑无缝地进行循环滚动显示。 在Android开发中,我们可以使用RecyclerViewViewPager来实现这样的横向无限循环滚动组件。 使用RecyclerView实现横向无限循环滚动组件的步骤如下: 1. 在布局文件中添加一个RecyclerView控件。 2. 创建一个RecyclerViewAdapter来管理数据和视图的显示。 3. 在RecyclerViewAdapter中实现循环滚动的逻辑,即在获取数据数量时设置为一个较大的数值,同时在对应位置获取数据时使用取余操作来实现循环滚动的效果。 4. 将RecyclerViewAdapter设置给RecyclerView控件。 使用ViewPager来实现横向无限循环滚动组件的步骤如下: 1. 在布局文件中添加一个ViewPager控件。 2. 创建一个PagerAdapter来管理数据和视图的显示。 3. 在PagerAdapter中实现循环滚动的逻辑,即在获取数据数量时设置为一个较大的数值,同时在对应位置获取数据时使用取余操作来实现循环滚动的效果。 4. 将PagerAdapter设置给ViewPager控件。 需要注意的是,在实现循环滚动效果时,需要根据具体的需求设置相应的滚动动画和手势操作等。另外,如果使用RecyclerView进行实现,还可以通过自定义LayoutManager来实现更加灵活的布局管理。总之,通过以上方法,我们可以实现Android横向无限循环滚动组件的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值