ViewPager实现循环滑动
来源:互联网 发布:node.js实战 pdf 下载 编辑:程序博客网 时间:2024/05/16 04:42
android中用ViewPager实现循环滑动
ViewPager在android开发中是个非常常用的组件,最为大家所熟悉的应用场景大概是在app中自动滚动的广告了。当然了,还有很多其它的地方也会用它来实现。不过美中不足的是,它没提供相应的API来实现循环滑动,当滑到最后一页后就不能前进了,只能回退,而当退到第一页时也不能再回退了。可我们的需求中往往有些地方需要循环的效果,比如上面说的广告,一般都是在ViewPager中放几张广告图,然后循环地滚动着。这样就要我们想点别的办法来达到要求。
目前网上主要有两种方法来解决这个问题。
方法一:
一种是方式是重写adapter的getCount方法,返回一个很大的数,比如Integer.MAX_VALUE,然后在初始化时从Integer.MAX_VALUE的二分之一处开始显示,因为这个值很大,所以基本不可能滑动到position=0或者position=Integer.MAX_VALUE的位置,使用户感觉是在循环。
其主要代码像这样:
private class MyAdapter extends PagerAdapter { private List<View> listView; public MyAdapter(List<View> listView) { this.listView = listView; } @Override public int getCount() { return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { int index = position % listView.size(); int i = container.indexOfChild(listView.get(index)); if (i != -1) { container.removeViewAt(i); } container.addView(listView.get(index)); return listView.get(index); } @Override public void destroyItem(ViewGroup container, int position, Object object) { }}
实际上这并不是真正的无限循环,如果只应用在手动滑的场景基本上不会出现滑到两端的情况,但如果是自动滑动的话这样做风险就比较大了。
方法二:
第二种方法是在原始数据的基础上增加一个头和尾,例如原始数据为[a1,b1,c1]三条数据,那么我们在头尾各增加一条数据变成[c2,a1,b1,c1,a2],c2与c1,a2与a1的内容是一样的,然后通过OnPageChangeListener中的onPageSelected方法判断viewpager是否滑到了头或滑到了尾,如到了头或尾就重新设置一下ViewPager的当前显示页,比如像上面的数据,当显示c2页的时候,就人为切换到c1,当显示a2的时候就人为切换到a1,这样无论往前往后滑都做到了真正的循环。
其主要代码是这样的:
@Overridepublic void onPageSelected(int position) { if (position == 0) { // 如果当前页是第1页,则跳到倒数第二页 setCurrentItem(mCount - 2, false); } else if (position == mCount - 1) { // 如果当前页是倒数第一页,则跳到第二页 setCurrentItem(1, false); }}
不过这种方法有一点瑕疵,就是在头尾切换的时候会闪一下,也就是从a1滑向c2或c1滑向a2的时候,动画还没有完成,即c2或a2还没有显示完整的时候就切到c1或a1去了,给人很不友好的体验,于是就有了本文要介绍的这种方法。
完美解决方案:
本方法的实现原理跟第二种方法是一样的,就是在第二种方法的基础上解决了会闪的问题。会闪的原因是动画还没执行完就已经调用onPageSelected方法了,导致我们的人为切换过早执行了,所以看起来像闪了一下。一开始我在那里加了一个延时,就是等待动画完成再执行切换,但是这个延迟的时间很难掌握,经常出现原本调好的时间到下次执行时又会闪,延时太长了也不行,如果连续滑动的话会滑不过去,要等一下才行,所以这不是个长久之计。后来搜索一番才知道原来有地方可以精确地知道动画已完成,就是onPageScrollStateChanged这个方法里面,当它的参数state的值为SCROLL_STATE_IDLE 时,就代表动画已完成了。这样就好办了,我们可以在这里执行我们的头尾切换工作。
其主要代码像这样:
@Overridepublic void onPageSelected(int position) { System.out.println("onPageSelected--->position = " + position); mCurrentItem = position;}@Overridepublic void onPageScrollStateChanged(int state) { switch (state) { case SCROLL_STATE_IDLE: // 已停止滑动 System.out.println("已停止滑动..." ); if (mCurrentItem == 0) { setCurrentItem(mCount - 2, false); } else if (mCurrentItem == mCount - 1) { setCurrentItem(1, false); } break; case SCROLL_STATE_DRAGGING: // 正在手动拖动 System.out.println("正在手动拖动..." ); break; case SCROLL_STATE_SETTLING: // 正在归位,即松手后自动完成滑动的过程 System.out.println("正在归位..." ); break; }}
效果图:
这样就完美的实现了循环滑动了。
最后,上源码:
demo源码:https://github.com/MingHuang1024/CyclicViewPager
番外篇
提个小问题:如果换一个场景,比如在日历中,我们每滑一下就显示下一个月或上一个月的日历,一般做个日历的话都要可以查询上百年的日期吧,如果使用上述方法,难道我们要传N多个view到ViewPagerAdapter里面吗?显然这是不可能的。如果只用三个view呢,让它们循环使用,这也有个问题,你怎么知道它滑到哪年哪月了呢?难道要自己用个计数器把它记起来?会不会太麻烦?下一篇来讲讲如何解决这个问题。请看大屏幕巧用ViewPager实现日历场景
由于水平有限,如果文中存在错误之处,请大家批评指正,欢迎大家一起来分享!
博客:http://blog.csdn.net/MingHuang2017
GitHub:https://github.com/MingHuang1024
Email:MingHuang1024@foxmail.com
微信:724360018
- ViewPager实现循环滑动
- ViewPager实现循环滑动
- ViewPager实现左右循环滑动
- ViewPager实现真循环滑动
- 使用ViewPager实现左右循环滑动
- 【Android开发】ViewPager实现左右循环滑动
- 使用ViewPager实现左右循环滑动图片
- 使用ViewPager实现左右循环滑动 总结
- Android ViewPager 实现无限循环滑动
- ViewPager实现左右无限循环滑动
- ViewPager实现循环滑动功能说明
- Viewpager完美实现左右循环滑动
- 使用ViewPager实现左右循环滑动
- Android Fragment+ViewPager实现循环滑动
- 使用ViewPager实现左右循环滑动
- 使用ViewPager实现左右循环滑动图片
- Android ViewPager实现无限循环滑动
- 实现ViewPager的左右循环滑动
- 整数分解为若干项之和(20 分)
- JavaWeb九大内置对象之request
- MySql数据库-02DDL语言(上)之操作数据库
- 手机灭屏,js定时器停止计算
- 第二周 PHP基础
- ViewPager实现循环滑动
- 安卓常用工具类-NotifyUtils【通知工具类】
- 输出全排列(20 分)
- IDEA编辑器运行Web项目时,导包成功,Tomcat却找不到包的解决方法(ClassNotFound)
- Django Web开发学习笔记一
- Docker下的Kafka学习之二:搭建集群环境
- node npm安装模块卡顿问题
- 二叉树求深度和叶子数(20 分)
- 数据库常用命令及基础知识