zoukankan      html  css  js  c++  java
  • Android L(5.0)源码之手势识别GestureDetector

    本人新手,最近下了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

     贴上源代码

     1     private class GestureHandler extends Handler {
     2         GestureHandler() {
     3             super();
     4         }
     5 
     6         GestureHandler(Handler handler) {
     7             super(handler.getLooper());
     8         }
     9 
    10         @Override
    11         public void handleMessage(Message msg) {
    12             switch (msg.what) {
    13             case SHOW_PRESS:
    14                 mListener.onShowPress(mCurrentDownEvent);
    15                 break;
    16                 
    17             case LONG_PRESS:
    18                 dispatchLongPress();
    19                 break;
    20                 
    21             case TAP:
    22                 // If the user's finger is still down, do not count it as a tap
    23                 if (mDoubleTapListener != null) {
    24                     if (!mStillDown) {
    25                         mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
    26                     } else {
    27                         mDeferConfirmSingleTap = true;
    28                     }
    29                 }
    30                 break;
    31 
    32             default:
    33                 throw new RuntimeException("Unknown message " + msg); //never
    34             }
    35         }
    36     }

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

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

    我的GitHub:https://github.com/lelelongwang
  • 相关阅读:
    痞子衡嵌入式:在IAR开发环境下RTThread工程自定义函数段重定向失效分析
    痞子衡嵌入式:深扒IAR启动函数流程之段初始化实现中可用的压缩选项
    痞子衡嵌入式:深扒IAR启动函数流程及其__low_level_init设计对函数重定向的影响
    《痞子衡嵌入式半月刊》 第 44 期
    痞子衡嵌入式:再测i.MXRT1060,1170上的普通GPIO与高速GPIO极限翻转频率
    痞子衡嵌入式:把玩i.MXRT1062 TencentOS Tiny EVB_AIoT开发板(1) 开发环境搭建与点灯
    痞子衡嵌入式:嵌入式CortexM系统中断延迟及其测量方法简介
    痞子衡嵌入式:把玩i.MXRT1062 TencentOS Tiny EVB_AIoT开发板(2) 在Flash调试及离线启动
    痞子衡嵌入式:利用GPIO模块来测量i.MXRT1xxx的系统中断延迟时间
    痞子衡嵌入式:在i.MXRT1170上启动含DQS的Octal Flash可不严格设Dummy Cycle (以MT35XU512为例)
  • 原文地址:https://www.cnblogs.com/longjunhao/p/4218549.html
Copyright © 2011-2022 走看看