• Android事件分发理解


    Android事件分发机制是个难点和重点,结合下各家,写点自己的理解。。

    首先抛出一个小问题,写一个button的点击事件

    [java] view plain copy
     
    1. button.setOnClickListener(new OnClickListener() {    
    2.     @Override    
    3.     public void onClick(View v) {    
    4.         Log.d("TAG", "onClick execute");    

    再写一个button的touch事件

    [java] view plain copy
     
    1. button.setOnTouchListener(new OnTouchListener() {    
    2.     @Override    
    3.     public boolean onTouch(View v, MotionEvent event) {    
    4.         Log.d("TAG", "onTouch execute, action " + event.getAction());    
    5.         return false;    
    6.     }    
    7. });    

    结果:

    如果把ontouch方法返回值改为true,结果:

    这是为什么?你先可以理解为返回true被消费了,不会往下传递了。

    你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法。那当我们去点击按钮的时候,就会去调用Button类里的dispatchTouchEvent方法,可是你会发现Button类里并没有这个方法,那么就到它的父类TextView里去找一找,你会发现TextView里也没有这个方法,那没办法了,只好继续在TextView的父类View里找一找,这个时候你终于在View里找到了这个方法,示意图如下:

    然后我们来看一下View中dispatchTouchEvent方法的源码:

    [java] view plain copy
     
    1. public boolean dispatchTouchEvent(MotionEvent event) {    
    2.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&    
    3.             mOnTouchListener.onTouch(this, event)) {    
    4.         return true;    
    5.     }    
    6.     return onTouchEvent(event);    
    7. }    

    看这个就明白了:刚才我们修改的outouch()方法return true,那么就走上面的if语句,被消费了没有执行click方法,如果outouch()ruturn false,那么dispatchTouchEvent()就ruturn onTouchEvent(event),说明了click方法一定在outouchEvent方法里面,点进去看下,果然

    [java] view plain copy
     
    1. public boolean performClick() {    
    2.     sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);    
    3.     if (mOnClickListener != null) {    
    4.         playSoundEffect(SoundEffectConstants.CLICK);    
    5.         mOnClickListener.onClick(this);    
    6.         return true;    
    7.     }    
    8.     return false;    
    9. }    

    ****************************************************************************************************************************
    接下来我们看一个图

    理解自:

    注意:

    • 目前所有的图的事件是针对ACTION_DOWN的,对于ACTION_MOVE和ACTION_UP后面再说。

    然后总结一下:1.有三层,Activity,ViewGroup,View, 然后呢,分别是dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent,理解为分发,拦截,消费,因为Activity和view在最上和最底层,所以没有onInterceptTouchEvent.

    2,接下来认真看下图,有三种返回值,return true,return false, return super,如果只走return super的话那么就是一个U型,整个流程应该是Activity---->ViewGroup--->View 从上往下调用dispatchTouchEvent方法,一直到叶子节点(View)的时候,再由View--->ViewGroup--->Activity从下往上调用onTouchEvent方法。

    只要分析dispatchTouchEvent它的四条线路就可以理解这幅图

    3.线路1:dispatchTouchEvent和onTouchEvent只要是返回true就是被消费了,没了,不会往下传了

    4.线路2:dispatchTouchEvent和onTouchEvent只要是返回false就会回溯给父空间的onTouchEvent处理,类似递归停止开始回溯。

    5.dispatchTouchEvent返回super.XXXX()那么就会交给这个ViewGroup的onInterceptTouchEvent 来处理,onInterceptTouchEvent (意思拦截,就是ViewGrouo分发的时候,问一问要不要拦截,如果拦截返回true,如果不拦截返回false,默认return super.onInterceptTouchEvent()就是return false),这里面再分两条路,线路3:到了onInterceptTouchEvent 返回true表示拦截,那么意思说自己要处理,就传给自己的onTouchEvent处理,线路4:onInterceptTouchEvent 默认或者返回false那么就交给子view的dispatchTouchEvent

    6.这个时候有人可能会有疑问,子view没有onInterceptTouchEvent ,那么怎么给它的onTouchEvent呢,为了让View可以把事件分发给自己的onTouchEvent,View的dispatchTouchEvent默认实现(super)就是把事件分发给自己的onTouchEvent

    *************************************************************************************************************************8

    关于ACTION_MOVE 和 ACTION_UP

     
    上面讲解的都是针对ACTION_DOWN的事件传递,ACTION_MOVE和ACTION_UP在传递的过程中并不是和ACTION_DOWN 一样,
    你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,
    只有前一个事件(如ACTION_DOWN)返回true,才会收到ACTION_MOVE和ACTION_UP的事件。

    对于ACTION_MOVE、ACTION_UP总结:ACTION_DOWN事件在哪个控件消费了(return true),
    那么ACTION_MOVE和ACTION_UP就会从上往下(通过dispatchTouchEvent)做事件分发往下传,就只会传到这个控件,不会继续往下传,
    如果ACTION_DOWN事件是在dispatchTouchEvent消费,那么事件到此为止停止传递,如果ACTION_DOWN事件是在onTouchEvent消费的,
    那么会把ACTION_MOVE或ACTION_UP事件传给该控件的onTouchEvent处理并结束传递。
     
     理解自:http://www.jianshu.com/p/e99b5e8bd67b,
    http://blog.csdn.net/guolin_blog/article/details/9097463
  • 相关阅读:
    攻防世界 resver catch-me
    elf.h
    攻防世界 reverse 进阶 notsequence
    攻防世界 reverse 进阶 easyre-153
    攻防世界 reverse 进阶 APK-逆向2
    寒假训练 roarctf_2019_realloc_magic(1/250)
    寒假任务
    Main_arena与non_main_arena
    wdb2018_guess
    :: namespace using作用
  • 原文地址:https://www.cnblogs.com/lyfshare/p/7196175.html
Copyright © 2020-2023  润新知