本人新手,最近下了Android L的源码,正在研究手势识别,能力有限,现总结如下:

Android识别触摸屏手势使得用户体验大大提高。在View类中有个View.OnTouchListener内部接口,通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些简单的touch事件,但是这个方法并不能识别手势,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)。好在Android为我们提供了GestureDetector类,通过它,我们可以轻松的进行手势识别。下面我做一个简要地介绍。

一.GestureDetector简介:

1.组成

GestureDetector类用来识别触摸屏的各种手势,它包含了两个接口和两个内部类:

接口:

  OnGestureListener:用来监听手势事件(6种)。

  OnDoubleTapListener:用来监听双击事件。

内部类:

  SimpleOnGestureListener:用来监听所有的手势。实际上它实现了上述两个接口,不过方法体是空的,需要我们自己写。我们可以继承这个类,重写里面的方法进行手势处理。

  GestureHandler:继承了Handler,这是5.0新加的内部类

2.构造(待续)

3.方法(待续)

4.使用

流程:

  首先,系统捕捉屏幕的触摸事件(onTouchListener),这时还未涉及具体手势,只是简单地捕捉到触摸。接着,在onTouch()方法中调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector来处理。最后,还需要实现抽象方法。

实现:

  (1)在Activity中创建GestureDetector实例gestureDetector。

  (2)可根据需要选择:

  重写OnGestureListener并通过构造函数传入gestureDetector

  重写OnDoubleTapListener并通过GestureDetector.setOnDoubleTapListener方法传入gestureDetector

  重写SimpleOnGestureListener并通过构造函数传入gestureDetector

  (3)重写Activity的onTouchEvent方法,将所有的触摸事件交给gestureDetector来处理

  public boolean onTouchEvent(MotionEvent event) {
    return gestureDetector.onTouchEvent(event);
  }

 二.接口OnGestureListener

1.onGestureListener识别6种手势,分别是:
  (1) onDown(MotionEvent e):down事件;
  (2) onSingleTapUp(MotionEvent e):一次点击up事件;
  (3) onShowPress(MotionEvent e):down事件发生而move或则up还没发生前触发该事件;
  (4) onLongPress(MotionEvent e):长按事件;
  (5) onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑动手势事件;
  (6) onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上拖动事件。

  关于onFling和onScroll的一点区别。
  onFling()是甩,这个甩的动作是在一个MotionEvent.ACTION_UP(手指抬起)发生时执行,而onScroll(),只要手指移动就会执行。他不会执行MotionEvent.ACTION_UP。onFling通常用来实现翻页效果,而onScroll通常用来实现放大缩小和移动。

2.重写

OnGestureListener onGestureListener=new OnGestureListener(){
  @Override
  public boolean onDown(MotionEvent e) {
  return false;
  }
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2,
  float velocityX, float velocityY) {
  return false;
  }
  @Override
  public boolean onLongPress(MotionEvent e) {
  return false;
  }
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2,
  float distanceX, float distanceY) {
  return false;
  }
  @Override
  public void onShowPress(MotionEvent e) {

  }
  @Override
  public boolean onSingleTapUp(MotionEvent e) {
  return false;
  }
  }
3.可以根据需要,在函数里添加具体的处理方法.之后通过构造函数传入GestureDetector即可。
  GestureDetector gestureDetector=new GestureDetector(this,onGestureListener);

三.接口OnDoubleTapListener

1.OnDoubleTapListener是用来检测鼠标双击事件的。需要实现的抽象方法有:

(1) onDoubleTap(MotionEvent e):双击事件。

(2) onDoubleTapEvent(MotionEvent e):双击间隔中还发生其他的动作。通知DoubleTap手势中的事件,包含down、up和move事件

(这里指的是在双击之间发生的事件,例如在同一个地方双击会产生DoubleTap手势,而在DoubleTap手势里面还会发生down和up事件,这两个事件由该函数通知)

(3) onSingleTapConfirmed(MotionEvent e):单击事件。用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,然后触发SingleTapConfirmed事件。

  关于onSingleTapConfirmed和onSingleTapUp的一点区别: OnGestureListener有这样的一个方法onSingleTapUp,和onSingleTapConfirmed容易混淆。二者的区别是:onSingleTapUp,只要手抬起就会执行,而对于onSingleTapConfirmed来说,如果双击的话,则onSingleTapConfirmed不会执行。

2.重写

OnDoubleTapListener onDoubleTapListener new OnDoubleTapListener() {
  @Override
  public boolean onSingleTapConfirmed(MotionEvent e) {
  return false;
  }
  @Override
  public boolean onDoubleTapEvent(MotionEvent e) {
  return false;
  }
  @Override
  public boolean onDoubleTap(MotionEvent e) {
  return false;
  }
)

可以根据需要,在函数里添加具体的处理方法.,之后通过setOnDoubleTapListener传入GestureDetector即可。
gestureDetector.setOnDoubleTapListener(onDoubleTapListener) ;

四.内部类SimpleOnGestureListener

SimpleOnGestureListener是GestureDetector类的一个内部类,该类是static class,也就是说它实际上是一个外部类。可以在外部继承这个类,重写里面的手势处理方法。

1.SimpleOnGestureListener实际上实现了OnGestureListener 和OnDoubleTapListener,所以它可以完成以上提到的所有手势识别(9种),如上介绍。

2.重写

public class simpleOnGestureListener extends SimpleOnGestureListener {

  @Override
  public boolean onDoubleTap(MotionEvent e) {
  return super.onDoubleTap(e);
  }
  @Override
  public boolean onDoubleTapEvent(MotionEvent e) {
  return super.onDoubleTapEvent(e);
  }
  @Override
  public boolean onDown(MotionEvent e) {
  return super.onDown(e);
  }
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float x,
  float y) {
  return super.onFling(e1, e2, x, y);
  }
  @Override
  public void onLongPress(MotionEvent e) {
  super.onLongPress(e);
  }
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float x,
  float y) {
  return super.onScroll(e1, e2, x, y);
  }
  @Override
  public void onShowPress(MotionEvent e) {
  super.onShowPress(e);
  }
  @Override
  public boolean onSingleTapConfirmed(MotionEvent e) {
  return super.onSingleTapConfirmed(e);
  }
  @Override
  public boolean onSingleTapUp(MotionEvent e) {
  return super.onSingleTapUp(e);
  }
}

可以根据需要,在函数里添加具体的处理方法,之后通过构造函数传入GestureDetector即可。

GestureDetector gestureDetector=new GestureDetector(this,simpleOnGestureListener );

五.内部类GestureHandler

贴上源代码

     private class GestureHandler extends Handler {
GestureHandler() {
super();
} GestureHandler(Handler handler) {
super(handler.getLooper());
} @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_PRESS:
mListener.onShowPress(mCurrentDownEvent);
break; case LONG_PRESS:
dispatchLongPress();
break; case TAP:
// If the user's finger is still down, do not count it as a tap
if (mDoubleTapListener != null) {
if (!mStillDown) {
mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
} else {
mDeferConfirmSingleTap = true;
}
}
break; default:
throw new RuntimeException("Unknown message " + msg); //never
}
}
}

六.另一种思路(我也没搞清楚)

要实现捕捉屏幕手势,除了在Activity中创建gestureDetector外,还有一种思路:构建一个Overlay,这个Overlay实现OnGestureListener接口,使其维护自己的GestureDetector。
在主视图上添加这个Overlay,并传入相应的listener,即可实现捕捉手势的功能。

Android L(5.0)源码之手势识别GestureDetector的更多相关文章

  1. [Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法

    博客首页:http://www.cnblogs.com/kezhuang/p/关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下<[Andr ...

  2. [Android FrameWork 6.0源码学习] LayoutInflater 类分析

    LayoutInflater是用来解析XML布局文件,然后生成对象的ViewTree的工具类.是这个工具类的存在,才能让我们写起Layout来那么省劲. 我们接下来进去刨析,看看里边的奥秘 //调用i ...

  3. [Android FrameWork 6.0源码学习] View的重绘过程之Draw

    View绘制的三部曲,测量,布局,绘画现在我们分析绘画部分测量和布局 在前两篇文章中已经分析过了.不了解的可以去我的博客里找一下 下面进入正题,开始分析调用以及函数原理 private void pe ...

  4. [Android FrameWork 6.0源码学习] ViewGroup的addView函数分析

    Android中整个的View的组装是采用组合模式. ViewGroup就相当与树根,各种Layout就相当于枝干,各种子View,就相当于树叶. 至于View类.我们就当它是个种子吧.哈哈! Vie ...

  5. [Android FrameWork 6.0源码学习] View的重绘过程

    View绘制的三部曲,  测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...

  6. [Android FrameWork 6.0源码学习] Window窗口类分析

    了解这一章节,需要先了解LayoutInflater这个工具类,我以前分析过:http://www.cnblogs.com/kezhuang/p/6978783.html Window是Activit ...

  7. [Android FrameWork 6.0源码学习] View的重绘过程之Layout

    View绘制的三部曲,测量,布局,绘画现在我们分析布局部分测量部分在上篇文章中已经分析过了.不了解的可以去我的博客里找一下 View的布局和测量一样,都是从ViewRootImpl中发起,ViewRo ...

  8. [Android FrameWork 6.0源码学习] View的重绘ViewRootImpl的setView方法

    博客首页:http://www.cnblogs.com/kezhuang/p/ 本篇文章来分析一下WindowManager的后续工作,也就是ViewRootImpl的setView函数的工作 /i* ...

  9. Android音乐播放器源码(歌词.均衡器.收藏.qq5.0菜单.通知)

    一款Android音乐播放器源码,基本功能都实现了 qq5.0菜单(歌词.均衡器.收藏.qq5.0菜单.通知) 只有向右滑动出现,菜单键和指定按钮都还没有添加. 源码下载:http://code.66 ...

随机推荐

  1. SQL Server 自定义快捷键

    SQL Server程序员经常要在SSMS(SQL Server Management Studio)或查询分析器(2000以前)中编写T-SQL代码.以下几个技巧,可以提升工作效率. 以下说明以SS ...

  2. Win7下用easyBCD引导安装Ubuntu15.04

    1 准备工作 easyBCD中添加一个启动项 修改启动项配置文件 注意两点:C盘设备号,镜像名称 title Install Ubuntu root (hd0,) kernel (hd0,)/vmli ...

  3. Mie散射 文献图片

    Technorati 标签: Mie Scattering,遥感,Remote Sensing

  4. ZOJ 2866 Overstaffed Company

    树状数组 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> ...

  5. HDU 2609 How many

    最小表示法+Map或者字典树,最小表示法找了个模板,还没学习呢... #include<cstdio> #include<cstring> #include<cmath& ...

  6. Chapter 1 First Sight——13

    It was just drizzling still, not enough to soak me through immediately as I reached for the house ke ...

  7. SqlServer批量导入

    SQL Server的Bulk Insert语句可以将本地或远程的数据文件批量导入到数据库中,速度非常的快.远程文件必须共享才行,文件路径须使用通用约定(UNC)名称,即"\\服务器名或IP ...

  8. android开发中应该注意的问题

    1. Activity可继承自BaseActivity,便于统一风格与处理公共事件,构建对话框统一构建器的建立,万一需要整体变动,一处修改到处有效.   2. 数据库表段字段常量和SQL逻辑分离,更清 ...

  9. Python3基础 Python的函数都有返回值 无指定返回值的函数 返回NONE对象

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  10. iis8.0配置 使用备忘 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容

    由于对iis的了解度不够,使用中总会碰到这样那样的问题,在这我先开个头,遇到问题再一一更新: 我用的是iis8; 1.发布到iis服务器下的网站你自己可以访问,局域网的其他机器不能? 答:是否开放了对 ...