Android 触摸事件传递机制

Android 触摸事件传递机制

1 触摸事件的类型

  • ACTION_DOWN : 用户手指按下操作,一般标志着触摸事件的开始.
  • ACTION_MOVE : 用户按下后移动手指.
  • ACTION_UP : 用户手指离开屏幕.触摸事件的结束.

一次屏幕的触摸操作中,ACTION_UP 和 ACTION_DOWN 是必须有的.ACTION_MOVE视情况而定.

2. 事件传递的三个阶段

  • 事件分发(dispatch) : 事件的分发对应着dispatchTouchEvent方法,在Android系统中所有的事件都是通过这个方法进行分发的.

    函数原型 :

    // 事件分发方法
    public boolean dispatchTouchEvent(MotionEvent ev);
    
    • 返回值 truefalse : 当前视图将事件消耗,不再继续分发给子视图.
    • 返回值 super.dispatchTouchEvent(ev) : 继续分发事件.
  • 事件拦截(Intercept) : 事件的拦截对应着onInterceptTouchEvent 方法.这个方法
    只有在ViewGroup及其子类中才存在,View和Activity中不存在.

    函数原型 :

    // 事件拦截
    public boolean onInterceptTouchEvent(MotionEvent ev);
    
    • 返回值 true : 拦截此事件,不再继续分发.同时交给自身的onTouchEvent方法进行消费.
    • 返回值 falsesuper.onInterceptTouchEvent : 不拦截事件,继续传递给子视图.
  • 事件消费(Consume) : 事件消费对应着 onTouchEvent 方法.

    函数原型 :

    // 消费函数
    public void onTouchEvent(MotionEvent ev);
    
    • 返回值 true : 当前视图可以处理当前事件,事件将不会向上传递给父视图.
    • 返回值 false : 当前视图处理不了该事件,事件会被传递给父视图的onTouchEvent方法进行处理.

3. Android拥有事件传递处理能力的类

  • Activity : 拥有 dispatchTouchEventonTouchEvent 方法.
  • ViewGroup : dispatchTouchEventonInterceptTouchEventonTouchEvent
  • View : : dispatchTouchEventonTouchEvent

4. View 的事件传递机制

参考代码 : app , 下面对程序及结果进行分析.

  • 不进行人为干预. 不设置listener情况.

    • dispatchTouchEventonTouchEvent 返回父类的同名方法.
    • onTouch 返回 false

    运行结果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MyTextView: onTouchEvent : DOWN
    MainActivity: onTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MainActivity: onTouchEvent : UP
    

    从LOG中可以看出事件传递方式如下 :

    • dispatchTouchEvent 方法从外层向内层传递.
    • onTouchEvent 从内层向外层传递.
    • 如果某一层处理了事,那么当前事件序列的其他事件不会向下传递.对于当前情况下由于MainActivity
      处理 ACTION_DOWN事件 所以该事件序列中的 ACTION_UP 事件也就到MainActivity就不
      再下发给子视图了.
  • 不进行人为干预,设置listener情况.

    onTouch返回false 运行结果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    
    MainActivity: MyTextView OnClick
    

    onTouch返回true 运行结果 :

    // onTouch 返回true : the listener consume the event
    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    

    LOG 信息显示事件是 MyTextView 视图处理的.

    • 事件处理的流程
      • 如果设置了listener则首先调用 listener 的 onTouch 方法.
        • 返回值 true : 表示listener处理该事件. onTouchEventonClick 不会被调用.
        • 返回值 false : 表示listener不处理该事件. onTouchEventOnClick 不会被调用.
      • onTouchEvent 如果onTouch 方法返回true
      • onClick 如果 onTouch 方法返回 true
  • dispatchTouchEvent 返回 falsetrue

    在两种情况下当前视图都会消耗该事件,该事件不会继续分发给子视图.
    同时不会调用onTouchEvent,onClick 等方法
    MainActivity 运行结果 :

    MainActivity: dispatchTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    

    MyTextView 运行结果

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    
  • onTouchEvent 方法返回 true

    当前视图消耗该事件,该事件处理不会向上传递. OnClick 方法不被调用

    MyTextView 运行结果

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    
  • onTouchEvent 方法返回 false

    当前视图不处理该事件,事件将会被传递给上层控件处理.并且 onClick 不会被调用.

    MyTextView 运行结果

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    MainActivity: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MainActivity: onTouchEvent : UP
    
  • onTouchEvent 返回 super.onTouchEvent(ev)

    MyTextView 运行结果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    
    MainActivity: MyTextView OnClick
    
    

5. ViewGroup 事件传递

  • onIntercepTouchEvent 返回 falsesuper.onIntercepTouchEvent

    在这种情况下,事件会继续分发.

    MyRelativeLayout 运行结果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyRelativeLayout: dispatchTouchEvent : DOWN
    MyRelativeLayout: onInterceptTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MyRelativeLayout: dispatchTouchEvent : UP
    MyRelativeLayout: onInterceptTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    MainActivity: MyTextView OnClick
    
  • onInterceptTouchEvent 返回 true

    在这种情况下,此视图会拦截事件,并交给自身的 onTouchEvent 处理.
    MyRelativeLayout 运行结果 :

    // 事件最终是Activity处理的.
    MainActivity: dispatchTouchEvent : DOWN
    MyRelativeLayout: dispatchTouchEvent : DOWN
    MyRelativeLayout: onInterceptTouchEvent : DOWN
    MyRelativeLayout: onTouchEvent : DOWN
    MainActivity: onTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MainActivity: onTouchEvent : UP
    

代码地址 : https://github.com/RichardFrankios/AndroidAdvanced

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容