博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 手势识别——单击/双击
阅读量:5883 次
发布时间:2019-06-19

本文共 7748 字,大约阅读时间需要 25 分钟。

为什么需要手势识别?

      手势对于我们的app有很多的地方都在使用,比如右滑关闭界面等。手势控制分为触发动作(Touch Mechanics,用户手指在屏幕上如何动作)和触发行为(Touch Activities,界面上特定动作在特定情境下引发的结果)。这是因为同样的触发动作(如单次触击)在不同情境下可能会带来不同的结果(如轻触,取消,开启/关闭指示),同样单次触发行为(如放大)可能是由多种触发动作(如捏放,双次触击,双次触击拖拽等)实现。

     一般情况下,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,但是这个方法太过简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)。

     sdk给我们提供了GestureDetector类,通过这个类我们可以识别很多的手势,主要是通过他的onTouchEvent(event)方法完成了不同手势的识别。虽然他能识别手势,但是不同的手势要怎么处理,应该是提供给程序员实现的。

GestureDetector这个类对外提供了两个接口和一个外部类,用于监听不同的手势

接口: OnGestureListener, OnDoubleTapListener
内部类: SimpleOnGestureListener

1、实现 GestureDetector.OnGestureListener

private class gesturelistener implements GestureDetector.OnGestureListener{    public boolean onDown(MotionEvent e) {        // TODO Auto-generated method stub          return false;    }    public void onShowPress(MotionEvent e) {        // TODO Auto-generated method stub      }    public boolean onSingleTapUp(MotionEvent e) {        // TODO Auto-generated method stub          return false;    }    public boolean onScroll(MotionEvent e1, MotionEvent e2,            float distanceX, float distanceY) {        // TODO Auto-generated method stub          return false;    }    public void onLongPress(MotionEvent e) {        // TODO Auto-generated method stub      }    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,            float velocityY) {        // TODO Auto-generated method stub          return false;    }}

实现该接口时,需要重载六个函数。 下面讲解一下这六个函数的触发条件(具体参看源码中的注释):

  • OnDown(MotionEvent e):用户按下屏幕就会触发;
  • onShowPress(MotionEvent e):如果是按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行。官方的注释如下:
/**         * The user has performed a down {@link MotionEvent} and not performed         * a move or up yet. This event is commonly used to provide visual         * feedback to the user to let them know that their action has been         * recognized i.e. highlight an element.         *         * @param e The down motion event         */
  • onLongPress(MotionEvent e):长按触摸屏,超过一定时长,就会触发这个事件
    触发顺序:
        onDown->onShowPress->onLongPress
  • onSingleTapUp(MotionEvent e):从名子也可以看出,一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会有这个触发,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以也就不会触发这个事件
        触发顺序:
        点击一下非常快的(不滑动)Touchup:
        onDown->onSingleTapUp->onSingleTapConfirmed
        点击一下稍微慢点的(不滑动)Touchup:
        onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
  • onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) :滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发  
    参数解释:(当滑动屏幕的速度较慢时,该方法不会被调用)
        e1:第1个ACTION_DOWN MotionEvent
        e2:最后一个ACTION_MOVE MotionEvent
        velocityX:X轴上的移动速度,像素/秒
        velocityY:Y轴上的移动速度,像素/秒  

注: 可以通过该函数里的滑动距离和滑动速度,判断是左滑还是右滑

  • onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY):在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法       在ACTION_MOVE动作发生时就会触发
        滑屏:手指触动屏幕后,稍微滑动后立即松开
        onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling
        拖动(当滑动的速度不是很快的时候,onFling函数最后不会被调用。)
        onDown------》onScroll----》onScroll

 

2、实现OnDoubleTapListener

/**  * The listener that is used to notify when a double-tap or a confirmed  * single-tap occur.  */

    OnGestureListener实现了单击相关的手势识别,对于双击相关的手势识别需要单独实现,下面具体介绍里面的几个方法:

private GestureDetector.OnDoubleTapListener mOnDoubleTapListener = new GestureDetector.OnDoubleTapListener() {        @Override        public boolean onSingleTapConfirmed(MotionEvent e) {            logger("onSingleTapConfirmed:");            return false;        }        @Override        public boolean onDoubleTap(MotionEvent e) {            logger("onDoubleTap:");            return false;        }        @Override        public boolean onDoubleTapEvent(MotionEvent e) {            logger("onDoubleTapEvent:"+MotionEvent.actionToString(e.getAction()));            return false;        }    };

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

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

onDoubleTap(MotionEvent e):双击事件

onDoubleTapEvent(MotionEvent e):双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件;下图是双击一下的Log输出:

3、实现SimpleOnGestureListener

/**     * A convenience class to extend when you only want to listen for a subset     * of all the gestures. This implements all methods in the     * {@link OnGestureListener}, {@link OnDoubleTapListener}, and {@link OnContextClickListener}     * but does nothing and return {@code false} for all applicable methods.     */    public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,OnContextClickListener{…..}

它与前两个不同的是:

1、这是一个类,在它基础上新建类的话,要用extends派生而不是用implements继承!
2、OnGestureListener和OnDoubleTapListener接口里的函数都是强制必须重写的,即使用不到也要重写出来一个空函数但在SimpleOnGestureListener类的实例或派生类中不必如此,可以根据情况,用到哪个函数就重写哪个函数,因为SimpleOnGestureListener类本身已经实现了这两个接口的所有函数,只是里面全是空的而已。

4、通过兼容包中工具识别手势

GestureDetector属于android.view包,android还提供了android.gesture包支持更多的手势操作。官方的介绍中使用了处理手势识别。 在识别手势的时候尽量使用 兼容包中手势识别。

public class MainActivity extends Activity implements        GestureDetector.OnGestureListener,        GestureDetector.OnDoubleTapListener{    private static final String DEBUG_TAG = "Gestures";    private GestureDetectorCompat mDetector;    // Called when the activity is first created.     @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // Instantiate the gesture detector with the        // application context and an implementation of        // GestureDetector.OnGestureListener        mDetector = new GestureDetectorCompat(this,this);        // Set the gesture detector as the double tap        // listener.        mDetector.setOnDoubleTapListener(this);    }    @Override    public boolean onTouchEvent(MotionEvent event){        this.mDetector.onTouchEvent(event);        // Be sure to call the superclass implementation        return super.onTouchEvent(event);    }    @Override    public boolean onDown(MotionEvent event) {        Log.d(DEBUG_TAG,"onDown: " + event.toString());        return true;    }    @Override    public boolean onFling(MotionEvent event1, MotionEvent event2,            float velocityX, float velocityY) {        Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());        return true;    }    @Override    public void onLongPress(MotionEvent event) {        Log.d(DEBUG_TAG, "onLongPress: " + event.toString());    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,            float distanceY) {        Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString());        return true;    }    @Override    public void onShowPress(MotionEvent event) {        Log.d(DEBUG_TAG, "onShowPress: " + event.toString());    }    @Override    public boolean onSingleTapUp(MotionEvent event) {        Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());        return true;    }    @Override    public boolean onDoubleTap(MotionEvent event) {        Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());        return true;    }    @Override    public boolean onDoubleTapEvent(MotionEvent event) {        Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString());        return true;    }    @Override    public boolean onSingleTapConfirmed(MotionEvent event) {        Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());        return true;    }}
View Code

有两个构造方法:一个构造方法入上述手势识别的代码,另一种增加了一个Handler参数,如下:

转载于:https://www.cnblogs.com/NeilZhang/p/8149186.html

你可能感兴趣的文章
选址攻略:数据中心选址要明了五大优势
查看>>
让计算变简单 | 信号高速路上,华为服务器是如何绕过那些“坑”的
查看>>
物联网快速发展 促进数据中心需要的爆炸性增长
查看>>
比自建 Hadoop 还便宜!云栖大会揭秘阿里云数加 MaxCompute
查看>>
《Web安全之机器学习入门》一 1.2 人工智能的发展
查看>>
谈3D打印技术在医疗行业的应用
查看>>
10 个最受欢迎的 Java 开发的 CMS 系统
查看>>
安全初创公司获百万风投资金的第一步:容器保护、人工智能和云安全
查看>>
与其说技巧不如叫它血泪史 路由器你真的会挑
查看>>
数据模型多了,应该怎么管?
查看>>
数据中心即使上云,硬件依然是关键
查看>>
云恶意软件是小题大做还是真的邪乎?
查看>>
数据的阴暗面:什么是暗数据?为什么暗数据很重要?
查看>>
网易2018校招内推编程题 彩色的砖块
查看>>
很多人不知道这是采用云技术的最大陷阱,包括你
查看>>
让IT安全人员夜不能寐的11个数据问题
查看>>
数据中心网络带宽性能测试方法介绍
查看>>
大数据平台技术发展脉络
查看>>
如何使用KNIME进行情感分析 | 中
查看>>
数据中心建设必须考虑哪些细节?
查看>>