zoukankan      html  css  js  c++  java
  • 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事件。

  • 相关阅读:
    配置码云git自动更新的webhook
    PHP如何像javabean一样get+字段名方式取值
    magento信用金额支付插件开发
    JAVASCRIPT localeCompare函数运用
    利用innodb_force_recovery 解决WAMP MySQL服务器无法正常启动的问题
    android回收AnimationDrawable动画的每一帧的图片资源,而释放内存
    MySQL 性能优化 30个数据库设计的最佳实践
    mydumper 快速高效备份mysql,按照表生成备份文件,快速恢复
    MySQL 5.6查询优化器新特性的“BUG” eq_range_index_dive_limit
    Mysql Innodb 引擎优化-内存、日志、IO、其他相关参数
  • 原文地址:https://www.cnblogs.com/tangZH/p/7029078.html
Copyright © 2011-2022 走看看