View事件分发

简介

1、View事件分发最重要的三个函数

  • dispatchTouchEvent
  • onInterceptTouchEvent-此方法只有ViewGroup有
  • onTouchEvent

2、View层事件处理的伪代码

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

3、事件传递顺序(在应用层面)

Activity->PhoneWindow->DecorView

4、处理事件的优先级onTouchListener.onTouch>onTouchEvent>onClickListener

if (onFilterTouchEventForSecurity(event)) {
    //noinspection SimplifiableIfStatement
    ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnTouchListener != null
            && (mViewFlags & ENABLED_MASK) == ENABLED

            //先执行TouchListener的onTouch方法,若返回false则onTouchEvent不会执行
            && li.mOnTouchListener.onTouch(this, event)) {
        result = true;
    }
    if (!result && onTouchEvent(event)) {
        result = true;
    }
}

Tips

1)

同一个事件序列是指从ACTION_DOWN事件开始,中间包含不定的ACTION_MOVE事件,最后以ACTION_DOWN事件结束。

2)

正常情况下,一个事件序列只能由一个View 拦截且消耗,一旦拦截,同一个事件序列中的所有事件都会直接交给该View处理,不会再调用onInterceptTouchEvent(即(3))。特殊情况下,在onTouchEvent中可以将事件强行传递到其他View。

3)

当一个View决定拦截一个事件(即使在半路拦截,即拦截ACTION_MOVE,ACTION_UP会直接交给他),系统会把同一个事件序列中的剩余事件统统交给他处理,直接调用它的onTouchEvent,不会调用onInterceptTouchEvent去再询问他。

4)

一旦事件交给一个View,如果他不消耗ACTION_DOWN事件(ACTION_DOWN返回false),事件序列中剩余的事件不会交给他处理,并且将事件传递给他的父元素处理,即onTouchEvent被调用。

5)

与4)相反,如果他只消耗ACTION_DOWN(返回true),而不消耗事件序列中的其他事件,这个事件不会重新传递到父元素,而是最终交给ACTIVITY处理,

6)

ViewGroup默认不拦截事件,返回false。

7)

View没有onInterceptTouchEvent方法,一旦有事件传递给他,会直接调用它的onTouchEvent。

8)

一般View都会默认消耗事件(返回true)。除非他是不可点击的(clickable和longclickable同时为true)。

9)

View的enable属性不影响onTouchEvent返回默认值,哪怕一个view是disable的,只要他的clickable或longclickable有一个为·true,那么onTouchEvent就可以返回true。

10)

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

11)

View事件传递是按照View树向下传递的,子View可以通过requestDisallowInterceptTouchEvent干预父元素的拦截事件的过程,除了ACTION_DOWN事件(这在解决View冲突可以派上用场)。

总结

  1. 父元素的拦截方法是绝对正义的!一旦拦截某一事件,剩余的都会被拦住,基本没有子元素的事了(好吧,这里子元素其实有个外挂requestDisallowInterceptTouchEvent,听这名字就知道可以对付父元素)。

  2. 事件ACTION_DOWN是个核心事件,如果你这个不消耗 ,那剩余事件你也就别想消耗了,掉别人嘴里了(其实就是父元素);如果你消耗了,就算你不想吃了,别人也吃不到(就是父元素),相当于就是扔掉了。

  3. View的enable问题,别看我是植物人(disable),只要我有嘴(clickable或longclickable为true)就会吃掉事件(返回true)。

  4. 貌似书上这里讨论的多是事件分发的冲突,没有太涉及到滑动冲突,一个View只要消耗掉down和up事件就可以完成click操作,View事件分发说到底其实是父元素与子元素的博弈与合作。

下一节:View滑动冲突处理,更激烈的父子博弈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值