0. 前言
欢迎转载,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52538723
我们在Android开发——View滑动的三种实现方式中学习了如何进行View滑动,在第一种方法,利用ScrollBy和ScrollTo进行滑动时,滑动效果是瞬间完成的,为了更好的用户体验,有时我们需要滑动有一个渐变的过程。这就是所谓的弹性滑动。
1. 延时策略
我们解决弹性滑动的第一反应可能就是采用延时策略,通过Handler发送并接收延时消息,每次接收到消息便完成一次ScrollTo操作,从而实现弹性滑动的效果。核心代码展示如下:
public void handleMessage(Message msg) { switch(mag.what){ case SCROLL_FRACTION:{ //if判断滑动还没有结束,结束则不再滑动和发送消息 if(){ //通过滑动完成比例计算该次滑动片段的位置点scrollX,scrollY View.scrollTo(scrollX,scrollY); mHandler.sendEmptyMessageDelayed(SCROLL_FRACTION, 20); } break; } default: break; } }
上述这种利用Handler发送延时消息的方式比较简单,但是需要注意的是,由于系统的消息调度需要时间,完成这次弹性滑动的时间总是大于if条件判断为true的次数乘以20ms(延迟消息的发送时间间隔)。
因此对弹性滑动完成总时间有精确要求的使用场景下,使用延时策略是一个不太合适的选择。
2. Scroller的使用
2.1 系统提供的Scroller
利用系统提供给我们的Scroller类,我们可以很方便的实现弹性滑动。代码比较简单,都是模版化的,如下所示:
Scroller scroller = new Scroller(mContext); private void smoothScrollTo(int destX, int destY){ int distanceX = destX - getScrollX(); int distanceY = destY - getScrollY(); //设置500ms的弹性滑动总时长 mScroller.startScroll(getScrollX(),getScrollY(),distanceX, distanceY, 500); //重绘 invalidate(); }
//该方法为空实现,因此需要重写 //该方法会被invalidate()方法触发执行 @override public void computeScroll(){ //判断滑动还没有结束 if(mScroller.computeScrollOffset()){ //通过Scroller类拿到下一步要滑动到的位置 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } }
这里说一下invalidate()和postInvalidate()的区别:
为了UI安全,invalidate()可在主线程直接调用刷新界面,而postInvalidate()会用Handler通知UI线程重绘屏幕,因此后者适用于子线程。
2.2 自定义Scroller
上面介绍了调用系统提供的Scroller的使用方法,但是Scroller类的getCurrX()、computeScrollOffset()等方法都是写死的。实现的弹性滑动是先快后慢的效果。
下面我们自行实现一个MyScroller类来完成匀速滑动的效果,同时也有助于理解系统Scroller类的实现原理。
/* * Created by SEU_Calvin on 2016/09/12 * 计算位移距离的自定义Scroller */ public class MyScroll{ private int startX; private int startY; private int distanceX; private int distanceY; private int duration; //开始执行动画的时间 private long startTime; //判断是否动画结束 private boolean isFinish; //计算当前距离 private long currentX; private long currentY; public MyScroll(Context context) { } public long getCurrX() { return currentX; } public long getCurrY() { return currentY; } public void startScroll(int startX, int startY, int distanceX, int distanceY, int duration) { this.startX = startX; this.startY = startY; this.distanceX = distanceX; this.distanceY = distanceY; this.duration = duration; this.startTime = SystemClock.uptimeMillis(); this.isFinish = false; } /* * Created by SEU_Calvin on 2016/09/12 * 判断是否滑动结束并改变将要被使用的currentX/Y */ public boolean computeScrollOffset() { if(isFinish){ return false; } //获得startTime到调用由于重绘导致computeScrollOffset()调用之间的passtime long passtime = SystemClock.uptimeMillis()-startTime; //计算currentX的值,指导下一步ScrollTo的位置 //startX/Y <currentX/Y<= startX/Y + distanceX/Y if(passtime<duration){ currentX = startX + distanceX*passtime/duration; currentY = startY + distanceY*passtime/duration; }else{ //运行结束 currentX = startX + distanceX; currentY = startY + distanceY; isFinish = true; } return true; } }
我们只要在调用时改变调用的MyScroll类即可。其他代码不做修改。
具体滑动效果,如匀速,匀加速,先慢后快等效果完全可以由MyScroll中自己的算法来决定。
以上就是对Android开发中弹性滑动的介绍。
转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52538723