Android UI 滚动、手势、速度的三个帮助类学习
2015-01-09 11:18
218 查看
Android提供了滚动帮助类Scroller,手势帮助类GestureDetector和速度帮助类VelocityTracker,之所以叫帮助类,是因为它们和正常的UI显示没有直接的关系,它们只是提供一些算法帮助,帮助我们得到想要的坐标值或者事件监听。下面分别讲一下这三个帮助类。
Scroller:
Scoller是自动滚动的帮助类,用到的场合是让某个控件自动滚动。比如有这么一个需求,我想让一个按钮5秒之内从(100,120)这个坐标滚动到(200,300)这个坐标。我们可以自己写代码,比如计算出每隔100毫秒应该滚动多少,然后用一个计时器或者直接用一个递归在5秒内让这个按钮不断执行draw方法,可以实现但是显然比较麻烦。那Scroller就是帮助我们实现这个功能的类,它帮我们提供了一种算法计算出了每次draw的时候应该滚动到哪里而不需要我们自己去计算了。
Scroller的用法比较简单:
在初始化控件的时候就可以初始化Scroller,然后在需要自动滚动的时候调用startScroll方法,然后在View的computeScroll方法里(这个方法会在View每次draw的时候调用),调用Scroller的computeScrollOffset方法,这个方法就是实现了刚才说的计算并返回滚动是不是应该结束的boolean,并且把计算结果赋值到Scroller的currentX和currentY中。然后在View的computeScroll里直接调用scrollTo滚动到这点就行了。滚动完以后,调用invalidate,然后又会调用到draw方法,然后又会调用到computeScroll方法,接着又会调用Scroller的computeScrollOffset方法。
这里View的computeScroll方法和内部调用的invalidate方法形成了间接递归。
GestureDetector:
关于手势,我们可以在view的onTouchEvent里做一些处理,比如根据用户两次点击的间隔判断是不是双击,比如可以计算用户抬起手指时的速度以进行一些其它操作,比如down的时候记下手指的坐标然后手指在view上移动的时候相减得到手指滑动了多少距离,当然要考虑一些多点触控。
上面的方式当然可以,但是同样也是比较麻烦。于是GestureDetector被设计出来了,他帮我们进行了上述的操作,我们只要实现相关监听方法就行了。
GestureDetector的用法如下:
初始化代码:
然后还有一点非常重要,就是在onTouch或者onInterceptTouchEvent等触摸时会调用的方法中加上截获相关事件(记得吗,GestureDetector知识个帮助类,只提供算法帮助)。
以上代码参照了 http://blog.csdn.net/harvic880925/article/details/39520901 。
VelocityTracker:
提供了速度的相关计算帮助。比如我想知道我此时的手指移动速度,如果自己计算的话,肯定会根据我手指移动的距离除以消耗的时间,当然要考虑其它很多因素,那VelocityTracker就是帮我们干这个的。
VelocityTracker的用法也很简单,如下:
也是在onTouch或者onInterceptTouchEvent等触摸时会调用的方法中加上截获相关事件:
mVelocityTracker.addMovement(event);
然后在ACTION_MOVE中:
就得到了当前x轴和y轴的滑动速度。
OK,这三个帮助类介绍到这里,谢谢阅读。
Scroller:
Scoller是自动滚动的帮助类,用到的场合是让某个控件自动滚动。比如有这么一个需求,我想让一个按钮5秒之内从(100,120)这个坐标滚动到(200,300)这个坐标。我们可以自己写代码,比如计算出每隔100毫秒应该滚动多少,然后用一个计时器或者直接用一个递归在5秒内让这个按钮不断执行draw方法,可以实现但是显然比较麻烦。那Scroller就是帮助我们实现这个功能的类,它帮我们提供了一种算法计算出了每次draw的时候应该滚动到哪里而不需要我们自己去计算了。
Scroller的用法比较简单:
在初始化控件的时候就可以初始化Scroller,然后在需要自动滚动的时候调用startScroll方法,然后在View的computeScroll方法里(这个方法会在View每次draw的时候调用),调用Scroller的computeScrollOffset方法,这个方法就是实现了刚才说的计算并返回滚动是不是应该结束的boolean,并且把计算结果赋值到Scroller的currentX和currentY中。然后在View的computeScroll里直接调用scrollTo滚动到这点就行了。滚动完以后,调用invalidate,然后又会调用到draw方法,然后又会调用到computeScroll方法,接着又会调用Scroller的computeScrollOffset方法。
这里View的computeScroll方法和内部调用的invalidate方法形成了间接递归。
@Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }
GestureDetector:
关于手势,我们可以在view的onTouchEvent里做一些处理,比如根据用户两次点击的间隔判断是不是双击,比如可以计算用户抬起手指时的速度以进行一些其它操作,比如down的时候记下手指的坐标然后手指在view上移动的时候相减得到手指滑动了多少距离,当然要考虑一些多点触控。
上面的方式当然可以,但是同样也是比较麻烦。于是GestureDetector被设计出来了,他帮我们进行了上述的操作,我们只要实现相关监听方法就行了。
GestureDetector的用法如下:
初始化代码:
mGestureDetector = new GestureDetector(new GestureListener()); mGestureDetector.setOnDoubleTapListener(new DoubleTapListener());这两个参数的类都是自己实现的相关监听者类,实现了监听者接口,
//OnGestureListener监听 private class GestureListener implements GestureDetector.OnGestureListener{ // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发 public boolean onDown(MotionEvent e) { Log.i("MyGesture", "onDown"); // Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show(); System.out.println("---------------------------onDown----------------"); return false; } /* * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发 * 注意和onDown()的区别,强调的是没有松开或者拖动的状态 * * 而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制, * 也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行, * 如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间 * (这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress),拖动了,就不执行onShowPress。 */ public void onShowPress(MotionEvent e) { Log.i("MyGesture", "onShowPress"); // Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show(); System.out.println("---------------------------onShowPress----------------"); } // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发 ///轻击一下屏幕,立刻抬起来,才会有这个触发 //从名子也可以看出,一次单独的轻击抬起操作,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以这个事件 就不再响应 public boolean onSingleTapUp(MotionEvent e) { Log.i("MyGesture", "onSingleTapUp"); // Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show(); System.out.println("---------------------------onSingleTapUp----------------"); return true; } // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.i("MyGesture", "onScroll:"+(e2.getX()-e1.getX()) +" "+distanceX); // Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show(); System.out.println("---------------------------onScroll----------------"+"onScroll:"+(e2.getX()-e1.getX()) +" "+distanceX); return true; } // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发 public void onLongPress(MotionEvent e) { Log.i("MyGesture", "onLongPress"); // Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show(); System.out.println("---------------------------onLongPress----------------"); } // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.i("MyGesture", "onFling"); // Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show(); System.out.println("---------------------------onFling----------------"); return true; } };
//OnDoubleTapListener监听 private class DoubleTapListener implements GestureDetector.OnDoubleTapListener{ public boolean onSingleTapConfirmed(MotionEvent e) { Log.i("MyGesture", "onSingleTapConfirmed"); // Toast.makeText(MainActivity.this, "onSingleTapConfirmed", Toast.LENGTH_LONG).show(); System.out.println("---------------------------onSingleTapConfirmed----------------"); return true; } public boolean onDoubleTap(MotionEvent e) { Log.i("MyGesture", "onDoubleTap"); // Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show(); System.out.println("---------------------------onDoubleTap----------------"); return true; } public boolean onDoubleTapEvent(MotionEvent e) { Log.i("MyGesture", "onDoubleTapEvent"); // Toast.makeText(MainActivity.this, "onDoubleTapEvent", Toast.LENGTH_LONG).show(); System.out.println("---------------------------onDoubleTapEvent----------------"+e.getAction()); return true; } };
然后还有一点非常重要,就是在onTouch或者onInterceptTouchEvent等触摸时会调用的方法中加上截获相关事件(记得吗,GestureDetector知识个帮助类,只提供算法帮助)。
/* * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector * 来分析是否有合适的callback函数来处理用户的手势 */ public boolean onTouch(View v, MotionEvent event) { boolean result=mGestureDetector.onTouchEvent(event); System.out.println("result---------------------:"+result); return result; }
以上代码参照了 http://blog.csdn.net/harvic880925/article/details/39520901 。
VelocityTracker:
提供了速度的相关计算帮助。比如我想知道我此时的手指移动速度,如果自己计算的话,肯定会根据我手指移动的距离除以消耗的时间,当然要考虑其它很多因素,那VelocityTracker就是帮我们干这个的。
VelocityTracker的用法也很简单,如下:
也是在onTouch或者onInterceptTouchEvent等触摸时会调用的方法中加上截获相关事件:
mVelocityTracker.addMovement(event);
然后在ACTION_MOVE中:
verTracker.computeCurrentVelocity(1000, mMaxVelocity); float velocityX = verTracker.getXVelocity(mPointerId); float velocityY = verTracker.getYVelocity(mPointerId);
就得到了当前x轴和y轴的滑动速度。
OK,这三个帮助类介绍到这里,谢谢阅读。
相关文章推荐
- 出色的用户体验有三个特征:速度快、响应及时以及无缝。下面的信息帮助你的应用如何能够在Android上实现这些特征
- 《计算机专业英语》对计算机的学习大有帮助
- 学习java i/o库要掌握的三个关键知识点
- 关于RDLC报表的一些总结,希望对正在学习使用它的朋友有所帮助
- 开心笑话,帮助你缓解大脑的疲劳和学习的压力
- 【学习指南】高考考生要远离三个复习误区
- 好东西大家分享:程序员学习的三个境界
- Windows编程基础--窗体篇(这篇文章可能会对你学习WINDOWS编程有些帮助)
- 这里提供有向导功能的命令行帮助你尝试学习ruby
- 【学习指南】高考考生要远离三个复习误区
- 一个用汇编写的引导区病毒例程,有时间可以分析一下,对各位学习汇编的朋友很有帮助!
- C#极限学习方法——挑战C#学习的最快速度 推荐
- BizTalk2006的帮助文件又更新了,对于还没有安装BizTalk环境又想学习的,不妨看看帮助先
- Linux命令学习(十):文件压缩命令及联机帮助命令
- C#极限学习方法——挑战C#学习的最快速度
- 真正开始学习,asp.net了,可是不知道怎么在新闻首页添加可以滚动的新闻条。
- [全程建模]三个问题的对话之三——学习的态度是什么?
- 需要进一步学习和思考的速度问题
- 简单的用 Java Socket 编写的 HTTP 服务器应用,帮助学习HTTP协议
- 学习java的建议和帮助