View事件分发

来源:互联网 发布:深圳编程培训机构 编辑:程序博客网 时间:2024/05/22 11:48

View事件分发

View本身的事件方法DOWN,MOVE,UP都会按照如下方式进行顺序执行:

  1. dispatchTouchEvent()
  2. setOnTouchListener()方法中的onTouch()方法
  3. onTouchEvent()

dispatchTouchEvent()源码

dispatchTouchEvent(MotionEvent event)中由如下代码段,决定了如上2,3的执行逻辑

    public boolean dispatchTouchEvent(MotionEvent event) {          if (!onFilterTouchEventForSecurity(event)) {              return false;          }          if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&                  mOnTouchListener.onTouch(this, event)) {              return true;          }          return onTouchEvent(event);      }  

在此段代码中,第2个if判断中有如下判断

  • mOnTouchListener!=null:即调用setOnTouchListener()方法
  • (mViewFlags & ENABLED_MASK) == ENABLED:标识View是否启用,大部分情况都为true
  • mOnTouchListener.onTouch(this, event) : 很关键的一段,此段决定当onTouch()方法返回true,方法将进入if中,直接返回,此时onTouchEvent()方法将不再执行。

总结:如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent

OnTouchEvent()源码

在View的onTouchEvent()方法中,有如下处理:

     if (((viewFlags & CLICKABLE) == CLICKABLE ||                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {           //...            return true;        } 

该段代码表明,如果View是可以点击或者可以长按的,则一定会返回true。

setOnLongClickListener()和setOnClickListener()执行逻辑

  • 如果同时设置了两个方法,则当长按时,是否执行onClick()方法取决于setOnLongClickListener()的返回值类型。
  • 如果setOnLongClickListener()返回false,则两个方法都会执行
  • 如果setOnLongClickListener()返回true,则会屏蔽点击事件。

onTouch()方法和onClick()的执行逻辑

  • 从上面的分析或者通过源码可知,onTouch()方法是在dispatchTouchEvent()中进行调用的,且其优先于onTouchEvent()方法。
  • onClick()方法是在onTouchEvent()中进行判断并调用performClick()方法进行调用的。

总结:onTouch()在onClick()之前进行调用,同时通过onTouch()和onToucEvent()的逻辑关系得出当onTouch()方法返回true时,onTouchEvent()不会执行,则onClick()方法也不会执行

View触摸事件的总结

  1. View是否调用onTouchEvent()方法,取决于dispatchTouchEvent()的返回值,在平常自定义View的时候,如果我们不重写dispatchTouchEvent()方法,则onTouchEvent()方法返回true,则能够处理触摸,如果返回false,则无法处理触摸事件。
  2. 如果重写dispatchTouchEvent()方法,则根据返回值两种情况:

    • return super.dispatchTouchEvent():依然取决于onTouchEvent();
    • return ture/false:onTouchEvent()将不会被调用。
  3. View 触摸事件顺序为 dispatchTouchEvent() - > onTouch() ->onTouchEvent().View是否能捕获触摸,取决于dispatchTouchEvent()返回值,返回true,则消费事件,返回false,则不消费事件。同时View默认实现的dispatchTouchEvent()方法已经实现了当前View下继续分发到onTouchEvent(),同时将onTouchEvent()结果作为返回值返回。

  4. 通常做法:dispatchTouchEvent()返回值一直返回return super.dispatchTouchEvent().重写onTouchEvent(),需要捕获时,强制返回true。。
  5. 当我们继承自View时,View的自身相关方法返回值, dispatchTouchEvent()返回值取决于onTouchEvent(),onTouchEvent()返回值,当View属性是clickable时,则返回true,否则返回false。

研究资料

Android触摸屏事件派发机制详解与源码分析一(View篇)
Android View 事件分发机制 源码解析 (上)

0 0
原创粉丝点击