
3.4.3 利用滚动器实现平滑翻页
在日常生活中,平移动画较为常见,有时也被称为位移动画。左右翻页和上下滚动其实都用到了平移动画,当然对于滚动视图、列表视图、翻页视图这些常用控件,Android已实现了位移动画,无须开发者劳心劳力。如果开发者自定义新的控件,就得自己编写这部分的滚动特效。
譬如平滑翻书的动画效果,就是位移动画的一种应用。用户先通过手势拉动书页,不等拉到底就松开手指,此时App需要判断当前书页是继续向前滚动还是往后缩回去。倘若书页的拉动距离超过屏幕宽度的一半,那么无疑应当继续前滚动到底;倘若书页的拉动距离尚未达到屏幕宽度的一半,那么应当往相反方向缩回去。对于这种向前滚动抑或向后滚动的判断处理,除了利用补间动画之外,还能借助滚动器(Scroller)加以实现。
滚动器不但可以实现平滑滚动的效果,还能解决拖曳时卡顿的问题。下面是滚动器的常用方法:
- startScroll:设置开始滑动的参数,包括起始的横纵坐标、横纵坐标偏移量和滑动的持续时间。
- computeScrollOffset:计算滑动偏移量。返回值可判断滑动是否结束,返回false表示滑动结束,返回true表示还在滑动中。
- getCurrX:获得当前的横坐标。
- getCurrY:获得当前的纵坐标。
- getFinalX:获得最终的横坐标。
- getFinalY:获得最终的纵坐标。
- getDuration:获得滑动的持续时间。
- forceFinished:强行停止滑动。
- isFinished:判断滑动是否结束。返回false表示还未结束,返回true表示滑动结束。该方法与computeScrollOffset的区别在于:
(1)computeScrollOffset方法会在内部计算偏移量,isFinished方法只返回是否结束的标志,而不做其他处理。
(2)computeScrollOffset方法返回false表示滑动结束,isFinished方法返回true表示滑动结束。
仍以平滑翻书为例,在自定义的滚动布局中,需要重写onTouchEvent方法,分别记录手势按下和松开之时对应的起点和终点,再计算两点在水平方向上的位移是否超过屏幕宽度的一半。超过则往前翻页,未超过则往后缩回,不管是前翻还是后缩,都得调用滚动器的startScroll方法执行滚动操作。同时重写布局的computeScroll方法,根据当前的滚动距离设置书页的偏移量,并在滚到终点时结束滚动操作。据此编写的滚动布局示例代码如下:
(完整代码见animation\src\main\java\com\example\animation\widget\ScrollLayout.java)



在布局文件中添加ScrollLayout节点,运行并测试该App后尝试左滑与右滑屏幕,可观察到平滑翻书效果如图3-41和图3-42所示。图3-41为松开手指时的画面,此时拉动距离超过了屏幕一半宽度;图3-42为书页滚动即将结束的画面,图片朝同方向继续滚动。

图3-41 松开手指时的画面

图3-42 书页即将滚动结束