Android View的事件分发机制笔记

来源:互联网 发布:c语言能做什么项目 编辑:程序博客网 时间:2024/05/23 22:01
  • 涉及到的几个概念:

    同一个事件序列:手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束。这个过程中产生的一系列事件,以down事件开始,中间可能包含多个move事件,最终以up事件结束。正常情况下,一个事件序列只能被一个view拦截且消耗,特殊情况下,这个view也可以将本该自己处理的事件通过onTouchEvent强行传递给子view处理。


  • 事件传递规则
    public boolean dispatchTouchEvent(MotionEvent ev)用于事件分发。返回结果表示是否消耗当前事件。
    public boolean onInterceptTouchEvent(MotionEvent ev)只有ViewGroup有该方法。用来判断是否拦截某个事件。返回结果表示是否拦截当前事件。默认返回false
    onTouchEvent(MotionEvent event)具体处理事件。返回结果表示是否消耗当前事件。如果不消耗,在同一个事件序列中,当前view无法再次接受到该事件。

上述3个方法关系伪代码如下(摘自《Android开发艺术探索》):

public boolean dispatchTouchEvent(MotionEvent ev) {        boolean consume=false;        if(onInterceptTouchEvent(ev))        {            consume=onTouchEvent(ev);        }else{            consume= child.dispatchTouchEvent();//由下级view的dispatchTouchEvent()决定。        }        return consume;    }

注意:当一个view被设置了OnTouchListener,这时OnTouchListener中的onTouch方法会优先于这个View的onTouchEvent方法。当且仅当OnTouchListener中的onTouch返回false时View自己的onTouchEvent会被执行。
view的dispatchTouchEvent源码

ViewGroup的dispatchTouchEvent部分源码

因此改进后的事件传递伪代码如下:

public boolean dispatchTouchEvent(MotionEvent ev) {        boolean consume=disallowIntercept;//由子View设置给父View        if(!consume)        {            consume=onInterceptTouchEvent(ev);        }        if(consume)        {            if(mOnTouchListener!=null)            {                consume=mOnTouchListener.onTouch(this,ev);//优先执行            }            if(!consume)            {                consume=onTouchEvent(ev);            }        }else{            consume= child.dispatchTouchEvent();        }        return consume;    }

事件传递顺序:Activity->Window->View

原创粉丝点击