zoukankan      html  css  js  c++  java
  • Android中Touch事件传递总结

    TouchEvent

    TouchEvent 分三种事件:down、move、up。

    其中move事件在一个操作中(这里说的一个操作就是用户与屏幕的交互,即由down到up的动作序列)可能会发生多次。
    但是,我们认为一个动作序列会包含以上三种事件,因此,在事件处理中就是要处理好这个过程,而最重要的就是down事件,这是一个动作序列的起始,没有down谈不上后面的事件了。
    所以,我们把消耗down事件的类当做是这个动作序列的最终载体。

    如果Down事件不归你处理,那这个动作序列的move,up也不归你处理。

    他们的触发顺序会是这样:

    ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP

    Touch事件传递的相关方法

    android系统中的几乎所有View的子类都具有下面三个和TouchEvent处理密切相关的方法:

    //这个方法用来分发TouchEvent
    public boolean dispatchTouchEvent(MotionEvent ev)
    
    //这个方法用来拦截TouchEvent 
    //只有ViewGroup包含此方法,普通view不包含方法
     public boolean onInterceptTouchEvent(MotionEvent ev)
    
    //这个方法用来处理TouchEvent 
    public boolean onTouchEvent(MotionEvent ev)

    onTouchEvent、onTouch

    OnTouchListener接口是用来处理手机屏幕事件的监听接口,需要实现该接口的onTouch事件/OnClick事件来设置触发事件,然后我们可以通过setOnTouchListener()为任何需要的View的子类添加该监听器。

    那么OnTouchListener接口中的onTouch方法 和 Touch事件的传递有什么关系呢?

    在onTouchEvent的源码中有这样一段:

    if (li != null && li.mOnClickListener != null) {  
                playSoundEffect(SoundEffectConstants.CLICK);  
               li.mOnClickListener.onClick(this);
                return true;  
            }

    若我们又注册了onClick监听,则在onTouchEvent中就会执行该监听,同时返回true。

    若没有注册onClick监听,顶层view的onTouchEvent默认返回false,其他层view的onTouchEvent默认返回true。

    因此,如果onTouch返回了true,则事件被消费掉,就不再执行onTouchEvent了,更别说onClick监听了。如果onTouch返回false,那么会继续执行onTouchEvent,再执行onClick监听,若onTouchEvent中返回了true,则事件被消费掉,不再往下层view传递。

    结论:onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。假若onTouchListener中的onTouch方法返回true,表示此次事件已经被消费了,那onTouchEvent是接收不到消息的。假如onTouch方法返回false,会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。

    Touch事件传递简易的流程图:

    绘图1

    结合图来看过程:

    如果返回值是 Super.dispatchTouchEvent ,意味着由onInterceptTouchEvent决定事件流向。

    如果调用了Super.dispatchTouchEvent。 这样就会继续调用onInterceptTouchEvent事件。因此如果需要多个控件同时处理,则一定需要返回true,并调用Super.dispatchTouchEvent

    也就是说想要把事件传递给子view,则Super.dispatchTouchEvent 是必不可少的。

    任何view的onTouch或者onTouchEvent方法返回了true,则表示该事件就已经到此被消费掉了,不再往下传递。

    其他:

    • Down事件在onInterceptTouchEvent()后返回true,则传递到onTouchEvent,当其返回true时,本次动作序列的后续事件不会再通过onInterceptTouchEvent了,而是在dispatchTouchEvent中直接传递于onTouchEvent。也就是说后续事件直接默认被该view的dispatchTouchEvent分发至onTouchEvent。
    • Down事件在onTouchEvent后返回false后导致本次事件没有被消费掉,则向上传递到父view的onTouchEvent,若返回true,则后续的move、up事件直接由父view的dispatchTouchEvent传递给自己的onTouchEvent,而不经过父view的onInterceptTouchEvent,后面的子view自然接收不到Touch事件。
    • onInterceptTouchEvent默认返回false,顶层view的onTouchEvent默认返回false,其他view的onTouchEvent默认返回true。
    • 如果我们在一个View中同时覆写了onClick、onLongClick及onTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能触发onClick或者onLongClick。

    GestureDetector手势识别类

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

    为View和Activity加入手势操作的步骤如下:

    1、为View或者Activity实现OnGestureListener接口,覆写需要的手势的回调方法。

    2、创建一个GestureDetector对象mygesturedetector,设置其监听器。

    3、覆写View或者Activity的OnTouchEvent方法,调用或返回mygesturedetector.onTouchEvent(ev),将事件交给mygesturedetector处理。

    非常好的参考资料:

    http://www.cnblogs.com/ghj1976/archive/2012/04/13/2445561.html  消息分发知识基础

    http://ipjmc.iteye.com/blog/1694146     Android事件处理

    http://www.longdw.com/touchevent-android/  Android的ViewGroup中事件的传递机制

     

  • 相关阅读:
    初级模拟电路:8-1 运算放大器概述
    初级模拟电路:6-1 FET概述
    初级模拟电路:5-5 甲乙类功率放大器
    初级模拟电路:5-4 乙类功率放大器
    初级模拟电路:5-3 变压器耦合型甲类功放
    初级模拟电路:5-2 串馈型甲类功放
    μC/OS-II系统中事件标志的使用
    STM32-SPI读写外部FLASH(W25Q64)
    STM32-定时器输出比较模式输出方波(DMA方式)
    STM32-定时器输出比较模式输出方波(中断方式)
  • 原文地址:https://www.cnblogs.com/shinefy/p/3931448.html
Copyright © 2011-2022 走看看