• View的事件分发机制


    View事件的分发机制由三个方法共同完成,这三个方法是:

    public boolean  dispatchTouchEvent(MotionEvent ev);

    public boolean onInterceptTouchEvent(MotionEvent ev);

    public boolean onTouchEvent(MotionEvent ev);

    它们之间的关系可以用下面的伪代码表示:

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

    从上面的伪代码中可以看出点击事件的传递规则是这样的:
    点击事件的传递是由外向内的,最先接受的到事件的是最外层的ViewGroup,这时候会调用dispatchTouchEvent方法(如果能够接收到事件,那么此方法一定会被调用),如果onInterceptTouchEvent方法返回的是true,那么就说明它要拦截这个事件,于是这个事件就交给该ViewGroup处理,也就是调用onTouchEvent方法。

    相反的,如果onInterceptTouchEvent的方法返回的是false,那么就说明该ViewGroup不拦截事件,事件会传递给它的子元素,子元素的dispatchTouchEvent方法会被调用,以此类推一直进行下去,直到事件最终被处理。

    如果该事件已经交给子view处理,但是子view的onTouchEvent方法返回了false(没有处理事件,或者处理事件失败了),那么父容器的onTouchEvent就会被调用(我们可以形象的认为下级处理事件失败,那么就由上级进行处理),以此类推上去,如果所有的元素都不处理这个事件,那么这个事件最终会传递给activity,activity的onTouchEvent方法会被调用。

    事件分发的时候传递顺序为Activity->Window->View.

    由上面的分析过程我们可以知道上面三个方法分别的作用是什么:

    dispatchTouchEvent:是用来分发事件的,如果事件能够传递到该view,那么该view的dispatchTouchEvent方法一定会被调用。

    onInterceptTouchEvent:用来判断是否拦截事件,返回true表示拦截,返回false表示不拦截。一旦事件被该view拦截,那么同一个事件序列中该方法不会再被调用。

    onTouchEvent:用来处理事件,返回true表示消耗,false表示不消耗。如果不消耗,那么同一个事件序列中当前的view无法再接收到事件。

    何为同一个事件序列:手指触摸屏幕的那一刻到手指离开屏幕的那一刻,这个过程中产生的一系列事件。

    (例如当你在滑动的时候:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE...->ACTION_UP

    onTouchEvent,OnTouchListener,OnClickListener的优先级:

    OnTouchListener>onTouchEvent>OnClickListener

    如何说呢:如果该view处理事件的时候设置了OnTouchListener,那么OnTouchListener方法里面的onTouch会被回调,若是onTouch返回了true,那么onTouchEvent不会被调用,反之onTouchEvent会被调用,此时若是设置了OnClickListener,那么在onTouchEvent中onClick方法会被调用。

    有几个需要注意的小点:

    1、一个view一旦开始处理事件,若它不消耗ACTION_DOWN事件(onTouchEvent返回了false),那么同一个事件序列的其他事件都不会再交给它处理,事件会交到父元素去处理(父元素的onTouchEvent会被调用)。若是该view消耗了ACTION_DOWN事件,但是不消耗其他事件,那么事件就会消失,最终这些消失的点击事件就会传递给Activity处理。

    2、ViewGroup默认不拦截所有的事件,它的onInterceptTouchEvent默认返回了false。

    3、view没有onInterceptTouchEvent方法,一旦有事件传递给它,那么它的onTouchEvent方法就会被带调用。

    4、view的onTouchEvent方法默认返回true,也就会说view默认会消耗事件,除非它是不了点击的,也就是它的clickable和longClickable同时被设置为false。事实上view的longClickable属性默认为false,clickable则要分情况,比如Button的clickable属性默认为true,TextView的clickable属性默认为false。

    5、view的enable属性不会影响onTouchEvent的默认返回值。即使其为disable状态,只要它的clickable或者longClickable有一个为true,那么它的onTouchEvent就返回true。

    6、onClick会发生的前提是当前的View是可点击的,并且它收到了down和up事件。

  • 相关阅读:
    vector, list, deque的选用(vector适用少量对象,list适用大量对象),以及效率问题
    MSYS是一个小型的GNU环境,包括基本的bash,make等等,与Cygwin大致相当(双击“D:MinGWmsys1.0msys.bat”,启动MinGW终端)
    你在为谁工作(陈凯元 2005 机械工业出版社)——薪水算什么,要为自己而工作;薪水只是工作的一种回报方式
    Net Core2.0下使用Dapper
    编程思想与算法
    NET Core Hosting
    windows/Linux下设置ASP.Net Core开发环境并部署应用
    OAuth2.0
    TF-IDF模型
    每分钟达百万的数据请求
  • 原文地址:https://www.cnblogs.com/tangZH/p/7029078.html
Copyright © 2020-2023  润新知