承接上一篇,如果你没有读过前四章方法,可以点击下面的链接:
http://www.cnblogs.com/fuly550871915/p/4985053.html
下面开始讲第五中方法。
五、利用Scroller类实现滑动
(1)基础知识总结
为了便于下面的阅读代码,先来总结一下关于Scroller类的基础知识。利用Scroller类实现滑动,需要三个步骤:
步骤一: 初始化Scroller对象,即mScroller = new Scroller(context)步骤二: 重写computeScroll()方法,实现模拟滑动。可以复制下面的末模板代码:
public void computeScroll() { super.computeScroll(); if(mScroller.computeScrollOffset()) { ((View)getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); } invalidate();//必须要调用 }
步骤三: 开启模拟过程,在合适的地方(一般都在move中)startScroll方法。它有两个重载方法如下: startScroll(int startX,int startY, int dx,int dy,int duration) startScroll(int startX,int startY,int dx,int dy) 方法中的参数无需多解释了,就是起始坐标与偏移量,还有完成偏移的时间而已。
需要说明的是:(1)computeScrollOffset方法用来判断是否完成了整个滑动,返回为true,则说明没有完成,否则则完成滑动。
(2)getCurrY以及getCurrX获得的是当前的滑动坐标。
(3)最后必须要用invalidate方法来刷新。因为computeScroll方法不会自动调用,是在draw方法中被调用的。所以
必须使用invalidate刷新,就会调用draw方法,自然就会调用computeScroll方法了。这样子就会实现循环调用。
(4)在startScroll中,偏移量跟使用scrollBy方法中的偏移量用法是一样的,即也必须填写你实际想要移动距离的相
反数。也就是你实际想让它偏移一个正值,这里就填写它相应的负值,如果想偏移一个负值,这里就填写相应的
正值!
(2)代码实践
有些东西还是需要在真正的代码中才能说的明白的。我们接着上一篇文章的代码继续编写。为了看清Scroller类是如何实现滑动的,我们
再次修改DragView的代码。这次修改的有些多。贴完整的代码出来。如下:
1 package com.example.testdragview; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.MotionEvent; 6 import android.view.View; 7 import android.widget.Scroller; 8 9 public class DragView extends View{ 10 11 12 private int lastX; 13 private int lastY; 14 private Scroller mScroller; 15 16 public DragView(Context context, AttributeSet attrs, int defStyleAttr) { 17 super(context, attrs, defStyleAttr); 18 19 mScroller = new Scroller(context); 20 } 21 22 public DragView(Context context, AttributeSet attrs) { 23 super(context, attrs); 24 mScroller = new Scroller(context); 25 } 26 27 public DragView(Context context) { 28 super(context); 29 mScroller = new Scroller(context); 30 } 31 32 33 34 public boolean onTouchEvent(MotionEvent event) { 35 36 //获取到手指处的横坐标和纵坐标 37 int x = (int) event.getX(); 38 int y = (int) event.getY(); 39 40 41 switch(event.getAction()) 42 { 43 case MotionEvent.ACTION_DOWN: 44 45 lastX = x; 46 lastY = y; 47 break; 48 49 case MotionEvent.ACTION_MOVE: 50 51 //计算移动的距离 52 int offX = x - lastX; 53 int offY = y - lastY; 54 55 View viewGroup = (View) getParent(); 56 57 //开启滑动 58 mScroller.startScroll(viewGroup.getScrollX(), 59 viewGroup.getScrollY(), -offX, -offY); 60 61 break; 62 63 case MotionEvent.ACTION_UP: 64 65 break; 66 } 67 return true; 68 } 69 70 71 72 public void computeScroll() { 73 super.computeScroll(); 74 75 if(mScroller.computeScrollOffset()) 76 { 77 ((View)getParent()).scrollTo(mScroller.getCurrX(), 78 mScroller.getCurrY()); 79 } 80 81 invalidate();//必须要调用 82 } 83 }
红色部分就是修改的核心代码了。需要说明的是,在开启滑动的代码中,即第58行,使用的是在父视图中使用getScrollX和getScrollY获取
所滑动到的点的坐标。而getScollX和getScrollY正是从computeScroll中的scrollTo方法中传递过来的。通过阅读源码你可以很清晰的看到这个
过程。我贴两张源码图吧,如下:
上图中观察mScrollX的传递过程,确实如上面我所说的。
而且在开启滑动的代码中,注意我们将偏移量可是都设定为负值了哦!(正如我上面所讲的设定为相反数即可)。
好了,关于代码的解释,就讲这么多,其他的都很好理解了。现在就运行程序,效果如下:
值得注意的是,我们的的DragView(即红色的块块)并不是即时跟随鼠标的滑动,在真机上这个效果将会更加突出!!其实这就是
Scrollerl类的滑动特点!即手指到达某一位置后,view会随后再平滑的到达这个位置,也就是说并不是view和手指一起到达指定位置的。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
因此,一般并不利用Scroller类实现滑动,因为它不是即时的。但却经常用它来实现手指抬起后,view回到初始位置!
来修改下DragView看看怎么实现这个效果。代码如下:
1 package com.example.testdragview; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.MotionEvent; 6 import android.view.View; 7 import android.widget.Scroller; 8 9 public class DragView extends View{ 10 11 12 private int lastX; 13 private int lastY; 14 private Scroller mScroller; 15 16 public DragView(Context context, AttributeSet attrs, int defStyleAttr) { 17 super(context, attrs, defStyleAttr); 18 19 mScroller = new Scroller(context); 20 } 21 22 public DragView(Context context, AttributeSet attrs) { 23 super(context, attrs); 24 mScroller = new Scroller(context); 25 } 26 27 public DragView(Context context) { 28 super(context); 29 mScroller = new Scroller(context); 30 } 31 32 33 34 public boolean onTouchEvent(MotionEvent event) { 35 36 //获取到手指处的横坐标和纵坐标 37 int x = (int) event.getX(); 38 int y = (int) event.getY(); 39 40 41 switch(event.getAction()) 42 { 43 case MotionEvent.ACTION_DOWN: 44 45 lastX = x; 46 lastY = y; 47 break; 48 49 case MotionEvent.ACTION_MOVE: 50 51 //计算移动的距离 52 int offX = x - lastX; 53 int offY = y - lastY; 54 55 ((View) getParent()).scrollBy(-offX,- offY); 56 57 break; 58 59 case MotionEvent.ACTION_UP: 60 61 View viewGroup = (View) getParent(); 62 63 //开启滑动,让其回到原点 64 mScroller.startScroll(viewGroup.getScrollX(), 65 viewGroup.getScrollY(), 66 -viewGroup.getScrollX() ,-viewGroup.getScrollY() ); 67 68 break; 69 } 70 return true; 71 } 72 73 74 75 public void computeScroll() { 76 super.computeScroll(); 77 78 if(mScroller.computeScrollOffset()) 79 { 80 ((View)getParent()).scrollTo(mScroller.getCurrX(), 81 mScroller.getCurrY()); 82 } 83 84 invalidate();//必须要调用 85 } 86 }
红色部分依旧是修改的核心代码。这里主要就是将实现的滑动效果替换成了用scrollBy来实现即时滑动,然后在手指抬起的up方法中,利用
Scoller类将view放回原来位置!运行一下,看看效果,如下:
如上图所示,只要鼠标一抬起,红色块块就会立刻回到原来位置!怎么样不错吧。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
好了,关于这个Scroller类的使用,就讲到这里。上面的代码基本都可以当做是模板代码了,需要的时候过来看看复制一下吧。
未完待续.....(最后一种方法)