《View的事件体系》(三)弹性滑动

           在《View的事件体系》(二)中,我们介绍了几种实现View滑动的方法,可以看出实现起来并不复杂,但是实现效果略显生硬,最理想的是渐进式的滑动,也就是弹性滑动。实现弹性滑动的方法很多,但都是一个思想:就是把一个大的滑动分成若干小的滑动并在一定的时间段内完成。下面介绍几种实现的方法:

 

(1)使用Scroller

     这种方法在《View的事件体系》(一)中已经贴出了源码,这里再分析一下:

Scroller scroller =new Scroller(context);

private void smoothScrollTo(int x,int y){

   int scrollX = getScrollX();

   int delta = x – scrollX;

   //1000秒内滑向x,慢慢移动

  scroller.startScroll(scrollX,0,delate,0,1000);

   invalidate();

}

@Override

public void computeScroll(){

  if(scroller.computeScrollOffset()){

     scrollTo(scroller.getCurrX(),scroller.getCurrY());

      postInvalidate();

}

}

       Scroller和View是两个不同的个体,代码的思路就是让Scroller先移动,然后让View跟着Scroller的脚步进行移动。代码中我们构造先一个Scroller并在smoothScrollTo中调用他的startScroll方法,startScroll方法的作用就是保存这几个参数,从左到右分别是滑动的起始X,Y坐标,终点X,Y坐标和整个滑动过程所需要的时间。真正完成滑动的是invalidate(),invalidate会让View重新绘制,在View的draw方法中又会去调用computeScroll方法,在View中computeScroll方法是一个空实现,在上面的代码中已经给出了实现。在computeScroll中,我们看到mScroller.computeScrollOffset(),他的作用不仅是判断滚动是否结束,而且根据时间的流逝的百分比计算出scrollX和scrollY改变的百分比,还在里面对Scroller.mCurrX和Scroller.mCurrY进行了赋值,也就是在滚动的过程中,实时的更新CurrX、CurrY的坐标。scrollTo(scroller.getCurrX(),scroller.getCurrY())就是让View跟着scroller改变位置。postInvalidate方法会进行第二次重绘,过程和第一次一样,如此反复,直到滑动结束。

       所以到这就明白了了, View的computeScroll和Scroller配合才能完成弹性滑动,他不断地让View重绘,每一次重绘距滑动起始时间都会有一个时间间隔,通过这个时间间隔,Scroller得到View下次滑动到的位置,继而View通过scrollTo完成滑动。这种设计简直绝妙!

 

(2)使用动画

    final int startX = 0;

    final int deltaX = 100;

    ValueAnimator  animator=ValueAnimator.ofInt(0,1).setDuration(1000);

     animator.addUpdateListener(newAnimatorUpdateListener(){

public void onAnimationUpdate(ValueAnimator animator){

    float fraction =animator.getAnimatedFraction();//fraction,分数

    button.scrollTo(stratX+(int)(deltaX*fraction),0);

}

}) ;

animator.start;

       在上面的代码中只是在1000ms内完成了整个动画过程。利用这个特性,我们就可以在动画的每一帧到来的时候获取动画完成的比例,进而根据这个比例计算出当前View所要滑动的距离。我们完全可以在onAnimationUpdate中加入其它想要的操作。

 

(3)延时策略

        通过发送一系列延时消息达到渐进式的效果,具体来说可以使用Handler或者View的postDelayed方法,也可以使用线程的sleep方法。对于前者我们利用postDelayed发送延时消息,在消息中让View滑动,接连不断的发送这种消息就可以实现弹性滑动的效果。对于后者来说通过在while循环中不断滑动View和sleep,就可以实现。下面以Handler为例:

private intmCount = 0;

intMESSAGE_SCROLL_TO = 0;

int FRAME_COUNT= 30;

int DELAYED_TIME= 33;

private Handlerhandler = new Handler(){

    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);

                    button.scrollTo(scrollX,0);

                     handler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,DELAYED_TIME);

                    

}break;

}

default:

     break;

}

};

};

       介绍这几种方法时更侧重思想,但结合前几篇讲解MotionEvent等关键概念,以及View的工作原理系列博文,便能进行进行灵活的扩展了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值