android 动画之Scroller
android中view的滑动是渐变的,用得比较多的弹性滑动是以下三种:
1. Scroller;
2. Handler#postDelayed;
3. Thread#sleep;
我们现在自定义一个类AutoScrollTextView,需求是传入x移动的距离,当调用它时,这个view水平渐变滑动。
class AutoScrollTextView extends View{ Scroller scroller = new Scroller(context); public void smoothScrollTo(int destX,int duration){ int scrollX = this.getScrollX(); int deltaX = destX - scrollX; //表示在duration时间内水平滑动deltaX的距离 scroller.start(scrollX,0,deltaX,0,duration); this.invalidate(); } //通过看View的源码,知道View的computeScroll()是空的,这就需要重写我们View中的方法computeScroll() @override public void computeScroll(){ if(scroller.computeScrollOffSet()){ this.scrollTo(scroller.getCurrentX(),scroller.getCurrentY()); postInvalidate(); } } //同理,通过看View的源码,知道View的ondraw()是空的,这就需要我们重新 @override protected void onDraw(){ super.onDraw(); computeScroll(); }}
从上面看到,我们调用了Scroller的start(),但又调用了View的invalidate(),那里面的具体操作是什么呢?我们来看下scroller这个start()的源码:
public void startScroll(int startX,int startY,int destX,int destY,int duration){ mMode = SCROLL_MODE; mFinished = false; mDuration = duration; mStartTime = AnimationUtils.currentAnimationTimeMills(); mStartX = startX; mStartY = startY; mFinalX = destX + startX; mFinalY = destY + startY; mDeltaX = destX; mDeltaY = destY; mDurationReciprocal = 1.0f/(float)mDuration;}
我们扯淡的发现,在Scroller的start()方法中,并没有我们期待的滑动操作,只是对一些参数进行了定义~
由此看到,Scroller并不能让view滑动,它只是跟view配合。当在smoothScrollTo()中调用view的invalidate()方法时,就会去调用view的ondraw()方法,而在ondraw()中又不断去调用computeScroll(),而这个computeScroll()在条件允许的情况下,又会不断去调用postInvalidate()方法,如此循环往复,直到条件不允许时,动画也就结束了!
再看下判断条件scroller.computeScrollOffSet()中做了什么:
public boolean computeScrollOffSet(){ int timePassed = (int)AnimationUtils.currentAnimationTimeMills()-mStartTime; if(timePassed < mDuration){ switch(mMode){ case SCROLL_MODE: final float x = mInterpolator.getInterpolation(timePassed*mDurationReciprocal); mCurrentX = mStartX + Math.round(x * mDeltaX); mCurrentY = mStartY = Math.round(y * mDeltaY); break; } }
从这里可得知,判断动画是否完成的标志,是mDuration和timePassed的相差值。
Scroller工作原理总结:
Scroller本身并不能实现view的滑动,它需要配合View的computeScroll方法才能完成弹性滑动的效果。它不断让view重绘,而在不断重绘过程中产生一个时间间隔,根据这个时间间隔能得到这个view当前的滑动位置,知道了滑动位置,就可以通过view的scrollTo方法来实现view的滑动。多次的小幅度滑动,就组成了弹性滑动。
更多相关文章
- 【Android】从无到有:手把手一步步教你使用最简单的 Fragment(一)
- Android中AppWidget加载流程(一)
- Android(安卓)Binder机制 - interface_cast和asBinder源码分析
- 设置Activity全屏
- Android(安卓)Test 基础知识
- Android(安卓)自定义view(二) 如何实现自定义组件
- android中处理json最佳方法
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用