在使用自定义视图的时候,对触屏事件的处理是比不可少的,有能力的可以自己写代码处理,这样更加的灵活。如果不想这么麻烦,Android提供了一个手势监听类GestureDetector,可以供我们使用。GestureDetector使用很方便,提供了单击,双击,长按等操作的处理,但是一般的定义界面都比较复杂,还用很多需要注意的地方,在这儿总结一下GestureDetector的使用。

首先新建一个空白的工程,主界面的layout中只需要添加一个按钮就行

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context=".MainActivity" >
  10. <Button
  11. android:id="@+id/btn_textgesture"
  12. android:layout_width="fill_parent"
  13. android:layout_height="fill_parent"
  14. android:text="@string/app_name" />
  15. </RelativeLayout>

复制代码

由于要测试的触屏事件,所有这个按钮比较大,主界面为如下效果: <ignore_js_op>首先介绍一下触屏事件处理的基本思路。触屏一般有三个基本事件,down按下,move移动,up离开,通过对这三个基本事件的监听,判断用户执行了何种操作。一个标准的触屏操作一般都是一系列基本事件的组合,在Android的框架中,通过onTouch()函数可以获取基本的触屏事件,而像onClick这样的函数,已经是一系列基本事件的组合。比如,发生了Down事件,在up事件之前没有发生move事件,或者move的范围很小,并且down事件和up事件的间隔很短,这就是一个click或者singelTap事件,对比实体键盘按键的事件,实体键盘是在down事件发生后进行操作,而触屏事件一般是up事件发生后进行操作。下面是activity的代码

  1. package com.example.testgesture;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.util.Log;
  5. import android.view.GestureDetector;
  6. import android.view.GestureDetector.SimpleOnGestureListener;
  7. import android.view.MotionEvent;
  8. import android.view.View;
  9. import android.view.View.OnTouchListener;
  10. import android.widget.Button;
  11. public class MainActivity extends Activity {
  12. private Button mButton;
  13. private GestureDetector mGestureDetector;
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_main);
  18. mGestureDetector = new GestureDetector(this, new MyOnGestureListener());
  19. mButton = (Button) findViewById(R.id.btn_textgesture);
  20. mButton.setOnTouchListener(new OnTouchListener() {
  21. @Override
  22. public boolean onTouch(View v, MotionEvent event) {
  23. Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));
  24. mGestureDetector.onTouchEvent(event);
  25. // 一定要返回true,不然获取不到完整的事件
  26. return true;
  27. }
  28. });
  29. }
  30. private String getActionName(int action) {
  31. String name = "";
  32. switch (action) {
  33. case MotionEvent.ACTION_DOWN: {
  34. name = "ACTION_DOWN";
  35. break;
  36. }
  37. case MotionEvent.ACTION_MOVE: {
  38. name = "ACTION_MOVE";
  39. break;
  40. }
  41. case MotionEvent.ACTION_UP: {
  42. name = "ACTION_UP";
  43. break;
  44. }
  45. default:
  46. break;
  47. }
  48. return name;
  49. }
  50. class MyOnGestureListener extends SimpleOnGestureListener {
  51. @Override
  52. public boolean onSingleTapUp(MotionEvent e) {
  53. Log.i(getClass().getName(), "onSingleTapUp-----" + getActionName(e.getAction()));
  54. return false;
  55. }
  56. @Override
  57. public void onLongPress(MotionEvent e) {
  58. Log.i(getClass().getName(), "onLongPress-----" + getActionName(e.getAction()));
  59. }
  60. @Override
  61. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  62. Log.i(getClass().getName(),
  63. "onScroll-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("
  64. + e2.getX() + "," + e2.getY() + ")");
  65. return false;
  66. }
  67. @Override
  68. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  69. Log.i(getClass().getName(),
  70. "onFling-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("
  71. + e2.getX() + "," + e2.getY() + ")");
  72. return false;
  73. }
  74. @Override
  75. public void onShowPress(MotionEvent e) {
  76. Log.i(getClass().getName(), "onShowPress-----" + getActionName(e.getAction()));
  77. }
  78. @Override
  79. public boolean onDown(MotionEvent e) {
  80. Log.i(getClass().getName(), "onDown-----" + getActionName(e.getAction()));
  81. return false;
  82. }
  83. @Override
  84. public boolean onDoubleTap(MotionEvent e) {
  85. Log.i(getClass().getName(), "onDoubleTap-----" + getActionName(e.getAction()));
  86. return false;
  87. }
  88. @Override
  89. public boolean onDoubleTapEvent(MotionEvent e) {
  90. Log.i(getClass().getName(), "onDoubleTapEvent-----" + getActionName(e.getAction()));
  91. return false;
  92. }
  93. @Override
  94. public boolean onSingleTapConfirmed(MotionEvent e) {
  95. Log.i(getClass().getName(), "onSingleTapConfirmed-----" + getActionName(e.getAction()));
  96. return false;
  97. }
  98. }
  99. }

复制代码

首先是声明一个GestureDetector,然后重写Button的onTouch函数,将触屏事件交给GestureDetector处理。首先做一个对按钮做一个单击 <ignore_js_op>onSingleTapUp被调用,说明发生了单击事件,onSingleTapConfirmed被调用,说明确认发生了一个单击事件,不是双击的事件。需要注意的是onSingleTapUp已经是一click事件,onSingleTapUp触发的时候是ACTION_UP事件。onSingleTapConfirmed是在用户手指离开屏幕后触发,所有up并不是所有触屏事件的结束。做一个双击的操作<ignore_js_op> 首先发生了一个onSingleTapUp,说明完成了一次单击事件,然后发生了onDoubleTap,至此,一次双击事件已经完成。我们可以看到,onDoubleTap发生的时候是ACTION_DOWN事件,也就是说双击事件是第二次按下屏幕的时候触发,而不是第二次离开屏幕的时候触发,在onDoubleTap发生之后,就可以在onDoubleTapEvent中监听到双击事件发生后从按下到弹起的所有触屏事件。onDoubleTap发生后不会触发onSingleTapUp和onSingleTapConfirmed。做一个长按的操作<ignore_js_op> onLongPress实在ACTION_DOWN时发生,onLongPress发生后在up之前不会用其他事件触发,可以在onShowPress处理状态的改变,比如按钮的按下状态。做一个滑动操作<ignore_js_op> onScroll事件是拖动,onFling是抛。结合log来了解一下。首先是ACTION_DOWN,之后多次ACTION_MOVE,移动超过一定距离,触发了onScroll,如果onScroll被触发,在up之前是不会有长按,单击,双击等事件的。看一下onScroll的参数

  1. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

复制代码

e1为第一次按下的事件,和onDown事件里面的一样,e2为当前的事件,distanceX为本次onScroll移动的X轴距离,distanceY为移动的Y轴距离,移动的距离是相对于上一次onScroll事件的移动距离,而不是当前点和按下点的距离。这次滑动最后触发了onFling事件,但是onFling事件的触发不是一定的,onFling是在ACTION_UP触发,平时列表在离开屏幕是继续滚动,就是通过这种方式触发。

  1. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

复制代码

onFling的前两个参数和onScroll相同,e2为用户拖动完离开屏幕时的点。veloctiyX,velocitY为离开屏幕时的初始速度,以这两个速度为初始速度做匀减速运动,就是现在拖动列表和拖动图片的各种缓存滚动的效果。函数的返回值除了onLongPress,这些函数都是有返回值的,

  1. mButton.setOnTouchListener(new OnTouchListener() {
  2. @Override
  3. public boolean onTouch(View v, MotionEvent event) {
  4. Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));
  5. mGestureDetector.onTouchEvent(event);
  6. // 一定要返回true,不然获取不到完整的事件
  7. return true;
  8. }
  9. });

复制代码

这些返回值会通过 mGestureDetector.onTouchEvent(event); 传递给onTouch。
最后总结一下GestureDetector结合SimpleOnGestureListener可以很方便的获取到单击,双击,长按等事件,但是对这些事件的处理不是简单的在对应的函数里做一些操作就可以的,复杂的自定义视图还是要在onTouch里面进行判断个个控件的焦点状态,而且GestureDetector也不是万能的,你如果要处理长按之后的移动,就要费一番功夫了,以为GestureDetector在长按发生后是不会在有onScroll的,你只能通过onTouch里面的ACTION_MOVE处理。

Android手势监听类GestureDetector的使用的更多相关文章

  1. Android手势监听

    public class MainActivity extends Activity { /* * 要实现手指在屏幕上左右滑动的事件需要实例化对象GestureDetector,new * Gestu ...

  2. Android 7.0 Gallery图库源码分析4 - SlotView手势监听及页面跳转

    上篇文章讲了初始化View时会实例化一个SlotView并监听其事件,至于它是怎么实现的,用的是Android自带的GestureDetector. GestureDetector是Android自带 ...

  3. Android开发之手势滑动(滑动手势监听)详解

    Android开发之手势滑动(滑动手势监听)详解 在Android应用中,经常需要手势滑动操作,比如上下滑动,或左右方向滑动,处理手势滑动通常有两种方法:一种是单独实现setOnTouchListen ...

  4. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

  5. Android来电监听和去电监听

    我觉得写文章就得写得有用一些的,必须要有自己的思想,关于来电去电监听将按照下面三个问题展开 1.监听来电去电有什么用? 2.怎么监听,来电去电监听方式一样吗? 3.实战,有什么需要特别注意地方? 监听 ...

  6. Android Listener 监听的几种写法

    Android中,View的Listener方法,在是否使用匿名类匿名对象时,有各种不同的写法. OnClickListener和其他Listener方法一样,都是View类的接口,重载实现后就能使用 ...

  7. Android 事件监听处理

    事件监听的处理模型包括三个成员:事件源.事件以及事件监听器. 基于监听的事件处理模型一般包括几个步骤: 1.获取普通界面组件: 2.实现事件监听器类 3.将监听器对象注冊给普通组件 当事件源上发生指定 ...

  8. Android 如何监听返回键,弹出一个退出对话框

    android 如何监听返回键点击事件,并创建一个退出对话框, 防止自己写的应用程序不小心点击退出键而直接退出.自己记录下这个简单的demo,备用. public class BackKeyTest ...

  9. Android:监听ListView

    本文目录 监听ListView点击事件 监听ListView滚动事件 监听ListView点击事件 使用监听器OnItemClickListener package com.example.tests ...

随机推荐

  1. 事件(event)

    事件概述 委托是一种类型可以被实例化,而事件可以看作将多播委托进行封装的一个对象成员(简化委托调用列表增加和删除方法)但并非特殊的委托,保护订阅互不影响. 基础事件(event) 在.Net中声明事件 ...

  2. C#_获取路径

    一.获取当前文件的路径 1.  System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName  获取模块的完整路径,包括文件名. ...

  3. 如何设置本机电脑的固定IP地址?

    最近使用Loadrunner需要用到IP欺骗,但是我打开设置IP欺骗却提示我:IP向导不支持启用DHCP的网卡.您的卡启用了DHCP或者配置了无效设置.请与系统管理员联系. 我就方了,于是百度了一下, ...

  4. mysql操作命令梳理(4)-中文乱码问题

    在平时的mysql运维操作中,经常会碰到插入中文字段后出现乱码的情况,产生中文乱码的原因一般有:1)mysql的编码格式不对,是latin1编码.强烈推荐将mysql下的编码格式都改为utf8,因为它 ...

  5. AnyProxy做App网络流量测试

    前言: AnyProxy是一个开放式的HTTP代理服务器.Github主页:[https://github.com/alibaba/anyproxy]主要特性包括: 基于Node.js,开放二次开发能 ...

  6. Redis常用操作-------Set(集合)

    1.SADD key member [member ...] 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略. 假如 key 不存在,则创建一个 ...

  7. UPC-5063-二分图最大匹配

    好吧二分图的最小点覆盖=最大匹配 这道题也就变成模板题了... 写一个提醒,在写二分图时,尽量清零操作清空为-1,比如这个题,匹配数组girl[]如果清空为0,代表每个点都与0点连接,但是实际上是并没 ...

  8. visual studio2013安装及测试

    visual studio2013自同学处拷贝安装至本机,由于安装包较大采用了双重压缩,解压时费了点时间,安装过程更是用了一个小时之久. 1.安装环境: 本机配置:Windows8,Intel(R)C ...

  9. 【个人博客作业II】有关代码规范问题的讨论

    参考课程辅导书<构建之法>可以知道,程序的代码规范常指代码风格规范和代码设计规范两个方面,其中:代码风格规范包括(缩进,行宽,括号,断行与空白行,分行,命名,下划线,大小写,注释这几个部分 ...

  10. 【补充】第一次个人项目出现的bug

    新程序包下载(密码:4kp6) >>>>>直接上代码,问题出在随机分数的生成上,确实出现了一些非常鱼唇的错误,不过已经提交了就没办法了,在这里发出来仅供参考吧: 修改前: ...