改变ViewPager的滑动速度,自定义动态设置切换动画时间

  • A+
所属分类:Android

ViewPager是一个非常常用的Android控件,除了列表页面并列的时候使用外,还有一个很常见的应用场景就是轮播图,也就是Carousel或者Banner,一般其展示内容都是图片或者广告之类的。往往在轮播图里,需要实现自动播放,即不需要用户用手指滑动ViewPager,也能自己不断的往下切换数据元素,当跳转到最后一条时,接下来又重新回到最开始的位置。

一般来说,实现自动播放与无限循环不难,前者使用RxJava或者Runnable+Handler实现定时器然后不断的给ViewPager调用setCurrentItem方法,后者则是在PagerAdapter的getCount方法设置一个极大的值(一般是整型的上限),并且利用好取余的方法来从实际的数据List里获取数据即可。

一切好像看起来好像都没啥问题,是吧?但作为一个要进阶的Android Developer,我们不能仅仅满足于功能的实现,而且还要考虑一下体验的问题。我们先用一个简单的Demo,实现一个非常原始的轮播图,多余的代码就不罗列了,主要给一下PagerAdapter的实现,以及用Runnable+Handler实现的定时轮播,其他代码可以参考ViewPager与PagerAdapter使用详解与源码解析一文。注意啦,内存泄漏、取消Runnable等操作请自行处理,我为了省事就不额外写代码了。

初始化了一些必要的数据:

然后就是实现一个PagerAdapter:

然后我们在给ViewPager绑定了PagerAdapter后,使用Runnable+Handler来实现轮播:

运行结果:

ViewPager default switching too fast

不过呢,很多人会注意到一个问题:切换的太快了!用户看到这么快的切换动画,体验不太好。如果这个切换过程能慢一点,就好多了。注意了,刚才我设置的postDelayed间隔是1秒钟,但切换间隔与此无关,即使你设置成10秒,在切换的时候依然速度快的飞起!想要改善用户体验,让切换动画变得慢一点是很有必要的。

然而,ViewPager并没有提供相应的接口,所以只能去看它的源码了。很幸运,我们可以在ViewPager的源码里,找到这样一个变量:

而且可以在源码里很清楚的看出来,setCurrentItem方法最终会调用smoothScrollTo(int x, int y, int velocity)方法,而其中又是依靠

这行代码,来把滑动动画的各种参数进行了设置,当然包括动画的持续时间。然后,再通过

来实现动画的执行。

显然,如果能把tartScroll(sx, sy, dx, dy, duration)中的duration值进行改动,就算完成了我们减慢ViewPager切换动画,动态设定动画时间的目标了。不过呢,这个duration只是smoothScrollTo方法内部的一个局部变量,我们是改动不了的,所以就需要另辟蹊径了。

思路并不麻烦,可以一步一步的推:我们需要修改mScroller.startScroll的duration参数,但是这个参数获取不到。那么如果我们自己去继承Scroller类,并且覆盖startScroll方法,调用super.startScroll(startX, startY, dx, dy, mDuration)的时候,直接把这个间隔时间的值改掉,不就可以了?不过,ViewPager源码中的mScroller是private私有的,显然,想要替换替换掉它,需要依赖反射了。下面给出实现的代码:

然后是通过反射来改变ViewPager中的mScroller:

这里我把动画执行时间设置为500毫秒,然后看一下运行结果:

ViewPager slow down after change scroller duration.

恩,这样的滑动速度就舒服多了。

KaelLi

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: