• android事件传递机制以及onInterceptTouchEvent()和OnTouchEvent()详解三之ACTION_CANCEL事件和事件回传


    ANDROID事件传递机制以及ONINTERCEPTTOUCHEVENT()和ONTOUCHEVENT()详解二之小秘与领导的故事

    ANDROID事件传递机制以及ONINTERCEPTTOUCHEVENT()和ONTOUCHEVENT()总结

    前两篇博文讲了onInterceptTouchEvent和OnTouchEvent的处理流程(没有看的赶紧去补下)

    声明:原创作品,转载请说明出处,来自 http://www.cnblogs.com/xiaoQLu/archive/2013/04/02/2994030.html

    ACTION_CANCEL事件,官方文档讲的是当前手势被释放,你将不会接收到其他的事件,应该向ACTION_UP一样对待它。

    那到底什么情况会触发这个事件呢?当 当前控件(子控件,儿子)收到前驱事件(ACTION_MOVE或者ACTION_MOVE)后,它的父控件(老爸)突然插手,截断事件的传递,这时,当前控件就会收到ACTION_CANCEL,收到此事件后,不管子控件此时返回true或者false,都认为这一个动作已完成,不会再回传到父控件的OnTouchEvent中处理,同时后续事件,会通过dispatchEvent方法直接传送到父控件这里来处理。这和之前的结论有点相悖,之前说过如果子控件的OnTouchEvent返回false,表明事件未被处理,是回传到父控件去处理的,这里纠正一下,只有ACTION_DOWN事件才可以被回传,ACTION_MOVE和ACTION_UP事件会跟随ACTION_DOWN事件,即ACTION_DOWN是哪个控件处理的,后续事件都传递到这里,不会上抛到父控件,ACTION_CANCEL也不能回传。还有一点,触摸区域的范围问题,如果触摸区域在子控件内,同时父控件没有截断事件传递,刚不管子控件是否拦截此事件,都会传递到子控件的OnTouchEvent中处理,可以看成一种责任吧,因为我点的就是你,你父亲没有拦截,说明他不想处理,那到你这里了,不管你拦不拦截,都得你来处理。

    结论:ACTION_CANCEL事件是收到前驱事件后,后续事件被父控件拦截的情况下产生,onTouchEvent的事件回传到父控件只会发生在ACTION_DOWN事件中

    实例说明:在下面的实例中,LinearView1是父控件,LayoutView2是子控件,点击区域是LayoutView2,可以看到父控件的onInterceptTouchEvent方法在ACTION_DOWN的时候没有拦截事件,但是在ACTION_MOVE的时候突然插手,拦截掉事件,这时候,子控件就会收到ACTION_CANCEL。

    
    
    public class LayoutView1 extends LinearLayout {
    
        private final String TAG = "LayoutView1";
    
        public LayoutView1(Context context, AttributeSet attrs) {
            super(context, attrs);
            Log.d(TAG, TAG);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            int action = ev.getAction();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "1:onInterceptTouchEvent action:ACTION_DOWN");
                //return true;
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "1:onInterceptTouchEvent action:ACTION_MOVE");
                return true;
                //break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "1:onInterceptTouchEvent action:ACTION_UP");
                //return true;
                break;
            case MotionEvent.ACTION_CANCEL:
                Log.d(TAG, "1:onInterceptTouchEvent action:ACTION_CANCEL");
                break;
            }
            return false;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            int action = ev.getAction();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "1:onTouchEvent action:ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "1:onTouchEvent action:ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "1:onTouchEvent action:ACTION_UP");
                break;
            case MotionEvent.ACTION_CANCEL:
                Log.d(TAG, "1:onTouchEvent action:ACTION_CANCEL");
                break;
            }
            return true;
        }
    }
    public class LayoutView2 extends LinearLayout {
        private final String TAG = "LayoutView2";   
    
        public LayoutView2(Context context, AttributeSet attrs) {
           super(context, attrs);
           Log.d(TAG,TAG);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
           int action = ev.getAction();
           switch(action){
           case MotionEvent.ACTION_DOWN:
               Log.d(TAG,"2:onInterceptTouchEvent action:ACTION_DOWN");
               break;
               //return true;
           case MotionEvent.ACTION_MOVE:
               Log.d(TAG,"2:onInterceptTouchEvent action:ACTION_MOVE");
               break;
               //return true;
           case MotionEvent.ACTION_UP:
               Log.d(TAG,"2:onInterceptTouchEvent action:ACTION_UP");
               break;
           case MotionEvent.ACTION_CANCEL:
               Log.d(TAG,"2:onInterceptTouchEvent action:ACTION_CANCEL");
               break;
           }  
           return false;
    }
     
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
           int action = ev.getAction();
           switch(action){
           case MotionEvent.ACTION_DOWN:
               Log.d(TAG,"2:onTouchEvent action:ACTION_DOWN");
               //return false;
               break;
           case MotionEvent.ACTION_MOVE:
               Log.d(TAG,"2:onTouchEvent action:ACTION_MOVE");
               return false;
               //break;
           case MotionEvent.ACTION_UP:
               Log.d(TAG,"2:onTouchEvent action:ACTION_UP");
               break;
           case MotionEvent.ACTION_CANCEL:
               Log.d(TAG,"2:onTouchEvent action:ACTION_CANCEL");
               break;
           }     
           return true;
        } 
    }

    有不明白的下载源码运行看看结果

    源码下载:https://files.cnblogs.com/xiaoQLu/MotionEventTest.rar

  • 相关阅读:
    Using Boost C++ libraries with gcc g++ under Windows(cygwin+netbeans)
    RFC中文目录
    GNU Make 学习笔记(一)
    make
    ODBC连接ORACLE数据库的设置
    windows下boost开发环境简易教程(cygwin+eclipse)
    GNU Make(二)
    C++虚函数表解析(转)
    如何判断adoquery中字段值是不是空值?
    Delphi ListView基本用法大全
  • 原文地址:https://www.cnblogs.com/xiaoQLu/p/2994030.html
Copyright © 2020-2023  润新知