实现弹性滑动的共同的思想:将一次大滑动分成若干次小的滑动并在一个时间段内完成。
弹性滑动方式:Scroller、动画、延时策略。
Scroller
以上就是Scroller的典型使用方法。
Sroller工作原理:当我们构造一个Scroller对象并且调用它的startScroll方法时,Scroller内部其实什么也没有做,它只是保存了我们传递的几个参数。仅仅调用startScroll是无法让View滑动的,因为它并没有做滑动相关的事情,接着就是调用invalidate方法,invalidate方法会导致View重绘,在View的draw方法中又会去调用computeScroll方法,computeScroll方法在View中是一个空实现,因此需要我们自己去实现,上图中的代码已经实现好了。
也就是说:当View重绘后会在draw方法中调用computeScroll,而computeScroll又会去向Scroller获取当前的ScrollX和ScrollY;然后通过ScrollTo方法实现滑动,接着又调用postInvalidate方法进行第二次重绘,这一次重绘的过程跟第一次重绘的过程一样,还是会导致computeScroll方法被调用,然后继续向Scroller获取当前的scrollX和ScrollY,并通过scrollTo方法滑动到新的位置,如此反复,直到整个过程结束。
概括:Scroller本身并不能实现View的滑动,它需要配合View的computeScroll方法才能完成弹性滑动的效果,它不断的让View重绘,而每一次重绘距滑动起始会有一个时间间隔,通过这个时间间隔Scroller就可以得出View当前的滑动位置,知道了滑动位置就可以通过ScrollTo方法完成View的滑动。就这样,View的每一次重绘都会导致View进行小幅度的滑动,而多次小幅度的滑动就组成了弹性滑动,这就是Scroller的工作机制。
通过动画
动画本身就是一种渐近的过程,通过它来实现的滑动天然就具有弹性效果。
ObjectAnimator.ofFloat(mTest,"translationX",0,100).setDuration(100).start();复制代码
使用动画监听addUpdateListener实现一些动画不能实现的效果:
private int startX = 0;private int deltaX = 100;private void myAnimation() {final ValueAnimator animator = ValueAnimator.ofInt(0, 1).setDuration(1000); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float fraction = animator.getAnimatedFraction(); mTest.scrollTo(startX + (int) (deltaX * fraction), 0); } }); animator.start();}复制代码
以上就是在1s内完成整个动画效果,注意这里是滑动View的内容,并不是View本身。
使用延时策略
public class ViewScrollerActivity extends AppCompatActivity { private Button mTest; private static final int MESSAGE_SCROLL_TO = 0; private static final int FRAME_COUNT = 30; private static final int DELAYED_TIME = 33; private int mCount = 0; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case MESSAGE_SCROLL_TO:{ mCount ++; if (mCount <= FRAME_COUNT){ float fraction = mCount/(float)FRAME_COUNT; int scrollX = (int)(fraction*100); mTest.scrollTo(scrollX,0); mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,DELAYED_TIME); } break; } default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_scroller); mTest = (Button) this.findViewById(R.id.test); mTest.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,DELAYED_TIME); } }); }}复制代码
xml:
复制代码