在使用自定义视图的时候,对触屏事件的处理是必不可少的,有能力的可以自己写代码处理,这样更加的灵活。如果不想这么麻烦,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 11 <Button 12 android:id="@+id/btn_textgesture" 13  android:layout_width="fill_parent" 14  android:layout_height="fill_parent" 15  android:text="@string/app_name" /> 16 17 </RelativeLayout>

由于要测试的触屏事件,所有这个按钮比较大,主界面为如下效果:

首先介绍一下触屏事件处理的基本思路。触屏一般有三个基本事件,down按下,move移动,up离开,通过对这三个基本事件的监听,判断用户执行了何种操作。一个标准的触屏操作一般都是一系列基本事件的组合,在Android的框架中,通过onTouch()函数可以获取基本的触屏事件,而像onClick这样的函数,已经是一系列基本事件的组合。

比如,发生了Down事件,在up事件之前没有发生move事件,或者move的范围很小,并且down事件和up事件的间隔很短,这就是一个click或者singelTap事件,

对比实体键盘按键的事件,实体键盘是在down事件发生后进行操作,而触屏事件一般是up事件发生后进行操作。

下面是activity的代码

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

首先是声明一个GestureDetector,然后重写Button的onTouch函数,将触屏事件交给GestureDetector处理。

首先做一个对按钮做一个单击

onSingleTapUp被调用,说明发生了单击事件,onSingleTapConfirmed被调用,说明确认发生了一个单击事件,不是双击的事件。需要注意的是onSingleTapUp已经是一click事件,onSingleTapUp触发的时候是ACTION_UP事件。onSingleTapConfirmed是在用户手指离开屏幕后触发,所有up并不是所有触屏事件的结束。

做一个双击的操作

首先发生了一个onSingleTapUp,说明完成了一次单击事件,然后发生了onDoubleTap,至此,一次双击事件已经完成。我们可以看到,onDoubleTap发生的时候是ACTION_DOWN事件,也就是说双击事件是第二次按下屏幕的时候触发,而不是第二次离开屏幕的时候触发,在onDoubleTap发生之后,就可以在onDoubleTapEvent中监听到双击事件发生后从按下到弹起的所有触屏事件。onDoubleTap发生后不会触发onSingleTapUp和onSingleTapConfirmed。

做一个长按的操作

onLongPress实在ACTION_DOWN时发生,onLongPress发生后在up之前不会用其他事件触发,可以在onShowPress处理状态的改变,比如按钮的按下状态。

做一个滑动操作

onScroll事件是拖动,onFling是抛。结合log来了解一下。首先是ACTION_DOWN,之后多次ACTION_MOVE,移动超过一定距离,触发了onScroll,如果onScroll被触发,在up之前是不会有长按,单击,双击等事件的。看一下onScroll的参数

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触发,平时列表在离开屏幕是继续滚动,就是通过这种方式触发。

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

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

函数的返回值

除了onLongPress,这些函数都是有返回值的,

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

这些返回值会通过 mGestureDetector.onTouchEvent(event); 传递给onTouch。

最后总结一下

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

本文转自 一点点征服   博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/7000304.html,如需转载请自行联系原作者

Android手势监听类GestureDetector的使用相关推荐

  1. Android 手势监听学习总结

    android的简单手势监听一般用onTouchListner接口,复杂手势监听一般用Detector来接替onTouch的处理. 手势监听后的处理涉及android坐标系统的问题. 多点触点则一般用 ...

  2. android 手势监听案例

    class MyGestureListener implements GestureDetector.OnGestureListener {@Overridepublic boolean onDown ...

  3. android手势监听功能吗,Android手势监听 OnGestureListener (短按,长按,慢滑动,快滑动)...

    /** * @以下方法中的参数解释: * @e1:第1个是 ACTION_DOWN MotionEvent 按下的动作 * @e2:后一个是ACTION_UP MotionEvent 抬起的动作(这里 ...

  4. Android 触摸屏交互之手势监听

    效果图 前言 2020年,智能手机大行其道,相信不会还有人用着老式的按键手机了吧,而智能手机最大的交互就是手机屏幕,其次的就是音量操作.生物识别(指纹+人脸+瞳孔).说白了用的最多的是手机的屏幕,屏幕 ...

  5. android新闻app实现下拉刷新,Android实例_当监听类有数据更新时下拉刷新

    之前两篇文章分别介绍了OnScrollListener的实现和ContentProvider监听数据的变化,下面我们就结合者两个知识点实现一个小项目 项目需求 使用当ContentProvider监听 ...

  6. Android——滑动监听SwipeRefreshLayout+瀑布流Recycl+Butter自动生成

    Android--滑动监听SwipeRefreshLayout+瀑布流Recycl+Butter自动生成 package c.example.jreduch09;import android.os.A ...

  7. Android实时监听网络状态

    Android开发实时监听网络状态变化一般有两种方法: 1. 新建一个基类BasicActivity.class,在基类中注册网络监听广播NetworkChangeReceiver.class,所有页 ...

  8. Android基于监听的事件处理机制

    Android提供了强大的事件处理机制,主要包括两大类: 1,基于监听的事件处理机制:主要做法是为Android界面组件绑定特定的事件监听器 2,基于回调的事件处理机制:主要做法是重写Android组 ...

  9. android动态监听事件,Android-常见的事件监听

    在Android的开发中,我们会遇到各种各样的事件监听.下面给大家分享一下,希望对Android感兴趣的小伙伴有帮助. Android常见的事件监听 单击事件onClickListener 长按事件o ...

  10. android 如何监听应用前后台切换

    今天,简单讲讲android如何判断应用切换到后台和应用切换到前台. 这个其实很简单,之前需要做一个功能,当app由后台进入前台时需要完成一些逻辑操作,所以在网上查找如何判断app由后台进入前台,最终 ...

最新文章

  1. OpenStack 系列之File Share Service(Manila)详解
  2. Spring Boot 添加拦截器的配置方式
  3. 解答MPLS基础的路由问题—Vecloud微云
  4. DAS、NAS、SAN区别
  5. 剪切粘贴时总是上次的内容_自学PS:拷贝与粘贴都有哪些方法?编辑信息时错误了怎样恢复?...
  6. 树形结构:递归转化为迭代,万能通用方法,分治策略基于栈的实现
  7. 适用于孩子,父母和祖父母的JBoss HornetQ –第1章
  8. MyBatis的搭建流程(idea+maven)
  9. 阿里云加入开放媒体联盟AOM 科技巨头联合推广高清视频新标准
  10. php sockets有什么用,PHP中Sockets与流有什么关系啊!!!!!
  11. 错误、调试和测试(4)-文档测试
  12. 南宁:“数字城管”让智慧城市建设提质提速
  13. WordPress个人博客Cosy3.1.3主题+积木部分插件
  14. 非线性方程求根方法——二分法
  15. vue中对token的有效期的理解
  16. narwal无法连接机器人_ABB机器人驱动通讯连接不上故障维修方法
  17. uni-app 组件注册
  18. warsong服务器维修,3.3冰冠要塞:最终巫妖王揭秘 技能介绍
  19. 诺禾-NFS 效劳器
  20. RationalDMIS 2020直线度评价

热门文章

  1. chatbot使用_使用Python设计ChatBot:一种改进的方法
  2. 让我们手动计算:深入研究Logistic回归
  3. Kardashev量表和AI:可能的床友
  4. 机器学习 神经网络 神经元_神经网络如何学习?
  5. lstm预测单词_从零开始理解单词嵌入| LSTM模型|
  6. 例2.3 日期差值 - 九度教程第6题(日期类问题)
  7. mysql建表指定表空间_Oracle中建表和指定表空间
  8. vivox6Android版本,vivo x6有几个版本?vivo x6各版本区别对比评测
  9. 如何监控微信小程序HTTP请求错误
  10. Redis分布式缓存安装和使用