《简述触摸屏手势识别》由会员分享,可在线阅读,更多相关《简述触摸屏手势识别(5页珍藏版)》请在金锄头文库上搜索。
1、简述 Android 触摸屏手势识别文章来源:很多时候,利用触摸屏的 Fling、Scroll 等 Gesture(手势)操作来操作会使得应用程序的用户体验大大提升,比如用 Scroll 手势在浏览器中滚屏,用 Fling 在阅读器中翻页等。在 Android 系统中,手势的识别是通过 GestureDetector.OnGestureListener 接口来实现的,不过 William 翻遍了 Android 的官方文档也没有找到一个相关的例子,API Demo 中的TouchPaint 也仅仅是提到了 onTouch 事件的处理,没有涉及到手势。Android Developer讨论组里也
2、有不少人有和我类似的问题,结合他们提到的方法和我所做的实验,我将给大家简单讲述一下 Android 中手势识别的实现。我们先来明确一些概念,首先,Android 的事件处理机制是基于 Listener(监听器)来实现的,比我们今天所说的触摸屏相关的事件,就是通过 onTouchListener。其次,所有 View的子类都可以通过 setOnTouchListener()、 setOnKeyListener()等方法来添加对某一类事件的监听器。第三,Listener 一般会以 Interface(接口)的方式来提供,其中包含一个或多个 abstract(抽象)方法,我们需要实现这些方法来完成
3、onTouch()、onKey()等等的操作。这样,当我们给某个 view 设置了事件 Listener,并实现了其中的抽象方法以后,程序便可以在特定的事件被 dispatch 到该 view 的时候,通过 callbakc 函数给予适当的响应。看一个简单的例子,就用最简单的 TextView 来说明(事实上和 ADT 中生成的 skeleton 没有什么区别)。view plain1.public class GestureTest extends Activity implements OnTouchListener 2. 3. Override 4. protected void onC
4、reate(Bundle savedInstanceState) 5. super.onCreate(savedInstanceState); 6. setContentView(R.layout.main); 7. 8. / init TextView 9. TextView tv = (TextView) findViewById(R.id.page); 10. / set OnTouchListener on TextView 11. tv.setOnTouchListener(this); 12. / show some text 13. tv.setText(R.string.tex
5、t); 14. 15. 16. Override 17. public boolean onTouch(View v, MotionEvent event) 18. Toast.makeText(this, “onTouch“, Toast.LENGTH_SHORT).show(); 19. return false; 20. 我们给 TextView 的实例 tv 设定了一个 onTouchListener,因为 GestureTest 类实现了OnTouchListener 接口,所以简单的给一个 this 作为参数即可。onTouch 方法则是实现了OnTouchListener 中的抽
6、象方法,我们只要在这里添加逻辑代码即可在用户触摸屏幕时做出响应,就像我们这里所做的打出一个提示信息。这里,我们可以通过 MotionEvent 的 getAction()方法来获取 Touch 事件的类型,包括 ACTION_DOWN, ACTION_MOVE, ACTION_UP, 和ACTION_CANCEL。ACTION_DOWN 是指按下触摸屏,ACTION_MOVE 是指按下触摸屏后移动受力点,ACTION_UP 则是指松开触摸屏,ACTION_CANCEL 不会由用户直接触发(所以不在今天的讨论范围,请参考ViewGroup.onInterceptTouchEvent(Motion
7、Event))。借助对于用户不同操作的判断,结合 getRawX()、getRawY()、getX()和 getY()等方法来获取坐标后,我们可以实现诸如拖动某一个按钮,拖动滚动条等功能。待机可以看看 MotionEvent 类的文档,另外也可以看考TouchPaint 例子。回到今天所要说的重点,当我们捕捉到 Touch 操作的时候,如何识别出用户的 Gesture?这里我们需要 GestureDetector.OnGestureListener 接口的帮助,于是我们的 GestureTest类就变成了这个样子。view plain1.public class GestureTest ext
8、ends Activity implements OnTouchListener, 2. OnGestureListener 3. 4. 随后,在 onTouch()方法中,我们调用 GestureDetector 的 onTouchEvent()方法,将捕捉到的 MotionEvent 交给 GestureDetector 来分析是否有合适的 callback 函数来处理用户的手势。view plain1.Override 2. public boolean onTouch(View v, MotionEvent event) 3. / OnGestureListener will anal
9、yzes the given motion event 4. return mGestureDetector.onTouchEvent(event); 5. 接下来,我们实现了以下 6 个抽象方法,其中最有用的当然是 onFling()、onScroll()和onLongPress()了。我已经把每一个方法代表的手势的意思写在了注释里,大家看一下就明白了。view plain1./ 用户轻触触摸屏,由 1 个 MotionEvent ACTION_DOWN 触发 2. Override 3. public boolean onDown(MotionEvent e) 4. / TODO Auto
10、-generated method stub 5. Toast.makeText(this, “onDown“, Toast.LENGTH_SHORT).show(); 6. return false; 7. 8. 9. / 用户轻触触摸屏,尚未松开或拖动,由一个 1 个 MotionEvent ACTION_DOWN 触发 10. / 注意和 onDown()的区别,强调的是没有松开或者拖动的状态 11. Override 12. public void onShowPress(MotionEvent e) 13. / TODO Auto-generated method stub 14.
11、15. 16. / 用户(轻触触摸屏后)松开,由一个 1 个 MotionEvent ACTION_UP 触发 17. Override 18. public boolean onSingleTapUp(MotionEvent e) 19. / TODO Auto-generated method stub 20. return false; 21. 22. 23. / 用户按下触摸屏、快速移动后松开,由 1 个 MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1 个 ACTION_UP 触发 24. Override 25. public boolean on
12、Fling(MotionEvent e1, MotionEvent e2, float velocityX, 26. float velocityY) 27. / TODO Auto-generated method stub 28. return false; 29. 30. 31. / 用户长按触摸屏,由多个 MotionEvent ACTION_DOWN 触发 32. Override 33. public void onLongPress(MotionEvent e) 34. / TODO Auto-generated method stub 35. 36. 37. 38. / 用户按
13、下触摸屏,并拖动,由 1 个 MotionEvent ACTION_DOWN, 多个 ACTION_MOVE触发 39. Override 40. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,41. float distanceY) 42. / TODO Auto-generated method stub 43. return false; 44. 我们来试着做一个 onFling()事件的处理吧,onFling()方法中每一个参数的意义我写在注释中了,需要注意的是 Fling 事件的处理代码
14、中,除了第一个触发 Fling 的 ACTION_DOWN和最后一个 ACTION_MOVE 中包含的坐标等信息外,我们还可以根据用户在 X 轴或者 Y轴上的移动速度作为条件。比如下面的代码中我们就在用户移动超过 100 个像素,且 X 轴上每秒的移动速度大于 200 像素时才进行处理。view plain1.Override 2.public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 3. float velocityY) 4. / 参数解释: 5. / e1:第 1 个 ACTION_DOWN MotionEvent 6. / e2:最后一个 ACTION_MOVE MotionEvent 7. / velocityX:X 轴上的移动速度,像素/秒 8. / velocityY:Y 轴上的移动速度,像素/秒 9. 10. / 触发条件 : 11. / X 轴的坐标位移大于 FLING_MIN_DISTANCE,且移动速度大于 FLING_MIN_VELOCITY个像素/秒 12. 13. if (e1.getX() - e2.getX() FLING_MIN_DISTANCE 14.