本人新手,最近下了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. 10317 Fans of Footbal Teams(并查集)

    10317 Fans of Footbal Teams 时间限制:1000MS  内存限制:65535K提交次数:0 通过次数:0 题型: 编程题   语言: G++;GCC Description ...

  2. 43个优秀的Swift开源项目推荐(转载)

    ["轮子"] 工具类 SwiftyJSON:GitHub 上最为开发者认可的 JSON 解析类 Dollar.swift:Swift 版 Lo-Dash (或 underscore ...

  3. HDU 2444 The Accomodation of Students

    首先是要构造二分图,然后二分图的最大匹配. 还有没完全证明过我的方法的正确性,但是AC了..... #include<cstdio> #include<cstring> #in ...

  4. 链接libtorrent库时出现的问题

    在QtCreator中使用libtorrent库的时候, 项目配置中 libs项配置如下: LIBS += -liconv -ltorrent-rasterbar -lboost_system -lb ...

  5. struts体系结构

    问题:   为什么 invoke()方法,一旦执行,表示action方法执行完毕,jsp页面已经处理完毕: 其返回值再修改无意义,不影响结果?? 解释: 着重看如下颜色的字: ■ ■ 官方文档有明确的 ...

  6. C# 通过接口 post 请求

    /// <summary> /// 提交数据请求 方法一 /// </summary> /// <param name="POSTURL">请求 ...

  7. 别在int与float上栽跟头(转)

    源:http://www.cnblogs.com/luguo3000/p/3719651.html int与float是我们每天编程都用的两种类型,但是我们真的足够了解它们吗.昨天在博客园看到一个比较 ...

  8. 服务器修改 ssh 22端口

    我们首先修改配置文件,让ssh 通知支持2个端口访问 ,22 和 23456 端口. Port 22 Port 23456 为什么要这样: 万一我用 23456端口替换了22端口,但是 23456正好 ...

  9. cakephp 的事件系统(Getting to grips with CakePHP’s events system), 基于观察者模式

    This article was written about CakePHP 2.x and has been untested with CakePHP 3.x CakePHP seems to g ...

  10. DWR 整合之Hibernate

    1.让 DWR 和 Hibernate 一起工作的检查列表 1.确保你使用的是最新的 DWR.Hibernate 转换器是新东西,所以你需要下载最新版本 2.确保你的 Hiberante 在没有 DW ...