zoukankan      html  css  js  c++  java
  • Android View事件分发机制 小记

    Android事件分发机制,一直以来只知道onInterceptTouchEvent返回true的时候,表示进行拦截,交给本身View的onTouchEvent处理;如果返回false,表示不进行拦截,交给子View处理。现在花一点事件对事件处理做一些总结。

      第一.研究对象。

             需要研究的对象,我将它分为两类,第一类:ViewGroup,也就是可以包含其他View或者ViewGroup;第二类,View,不能包含其他View。这两类的差别在于ViewGroup,包含dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent方法。而View只包含onTouchEvent方法。(注意我这里说的View和android上定义的View有差别,androi上ViewGroup是继承View的)。

      第二.研究的主要函数。

             研究的函数包括三个:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent。它们之间的关系可以用伪代码表示:

    public boolean dispatchTouchEvent(Motiontion ev){
       boolean consume=false;
       if(onInterceptTouchEvent(ev)){
          consume=onTouchEvent(ev);
       } else{
          consume=child.dispatchTouchEvent(ev);
       }
        return consume;
    }

         我的理解:若onInterceptTouchEvent进行拦截了,则返回onTouchEvent(ev)的值;否则交给子View去处理。

    第三。几种情况分析。

          接下去,我写了1个Demo进行测试,布局比较简单,父View里头套了一个子View。

          1.若父View的onInterceptTouchEvent中的Down返回true,则子View不会接收到touch事件。

           父View的代码:

      @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            int action = ev.getActionMasked();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
    
                flag = true;
                Log.e("error", "father_inter_action_down="+flag);
                break;
            case MotionEvent.ACTION_MOVE:
    
                Log.e("error", "father_inter_action_move");
                break;
    
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                Log.e("error", "father_inter_action_cancel");
                break;
            default:
                break;
            }
            return flag;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int action = event.getActionMasked();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
    
                touchFlag = true;
                Log.e("error", "father_touch_action_down");
                break;
            case MotionEvent.ACTION_MOVE:
    
                Log.e("error", "father_touch_action_move");
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
    
                Log.e("error", "father_touch_action_cancel");
                break;
            default:
                break;
            }
            return touchFlag;
    
        }
    
    }

         子View的代码:

    public boolean onTouchEvent(MotionEvent event) {
            int action = event.getActionMasked();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
    
                touchFlag = true;
                Log.e("error", "child_touch_action_down");
                break;
            case MotionEvent.ACTION_MOVE:
    
                Log.e("error", "child_touch_action_move");
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
    
                Log.e("error", "child_touch_action_cancel");
                break;
            default:
                break;
            }
            return touchFlag;
    
        }

       LOG日志为:

    01-04 21:46:36.724: E/error(12032): father_inter_action_down=true
    01-04 21:46:36.726: E/error(12032): father_touch_action_down
    01-04 21:46:36.759: E/error(12032): father_touch_action_move

    ……
    01-04 21:46:36.776: E/error(12032): father_touch_action_move
    01-04 21:46:37.178: E/error(12032): father_touch_action_cancel

       结论:从log中可以看到 子View 没有获得touch事件。

    2.若父View的onInterceptTouchEvent中的Down返回false,并且子View中Touch事件返回True。

       代码部分:

              父View中的onInterceptTouchEvent:          

               case MotionEvent.ACTION_DOWN:
                flag = false;
                Log.e("error", "father_inter_action_down="+flag);
                break;


                子View中的TouchEvent返回true。

                LOG日志为:

    01-04 21:17:08.974: E/error(30622): father_inter_action_down=false
    01-04 21:17:08.975: E/error(30622): child_touch_action_down
    01-04 21:17:09.004: E/error(30622): father_inter_action_move
    ……
    01-04 21:17:09.336: E/error(30622): father_inter_action_move
    01-04 21:17:09.337: E/error(30622): child_touch_action_move
    01-04 21:17:09.350: E/error(30622): father_inter_action_cancel
    01-04 21:17:09.351: E/error(30622): child_touch_action_cancel

              结论:从上诉可以看出,父View并不会再调用自己的onTouch方法,但是之后的事件:ACTION_MOVE和ACTION_DOWN都会经过父View的onInterceptTouchEvent方法,由于均未进行拦截。所以这些后续事件都传到了子View中。

    3.若父View的onInterceptTouchEvent中的Down返回false,并且子View中Touch事件返回false。

       Log日志为:

    01-04 21:18:21.334: E/error(851): father_inter_action_down=false
    01-04 21:18:21.335: E/error(851): child_touch_action_down
    01-04 21:18:21.335: E/error(851): father_touch_action_down
    01-04 21:18:21.368: E/error(851): father_touch_action_move
    01-04 21:18:21.384: E/error(851): father_touch_action_move
    01-04 21:18:21.401: E/error(851): father_touch_action_move

    ……
    01-04 21:18:21.783: E/error(851): father_touch_action_move
    01-04 21:18:21.800: E/error(851): father_touch_action_move
    01-04 21:18:21.801: E/error(851): father_touch_action_cancel

    结论:从上诉可以看出,子View未消耗该touch事件,则该事件向上进行传递,调用父View的onTouch方法(不调用onInterceptTouchEvent方法),由于父View中的onTouch方法对所有事件都返回了True,表示对所有事件进行消耗。

  • 相关阅读:
    Delphi利用Windows GDI实现文字倾斜
    再学 GDI+文本输出文本样式
    GDI+在Delphi程序的应用 Photoshop色相饱和度明度功能
    GDI+图像与GDI位图的相互转换
    走进JavaWeb技术世界12:从手动编译打包到项目构建工具Maven
    走进JavaWeb技术世界11:单元测试框架Junit
    走进JavaWeb技术世界10:从JavaBean讲到Spring
    走进JavaWeb技术世界9:Java日志系统的诞生与发展
    走进JavaWeb技术世界8:浅析Tomcat9请求处理流程与启动部署过程
    随笔总和
  • 原文地址:https://www.cnblogs.com/woshidalao/p/5100416.html
Copyright © 2011-2022 走看看