TouchEvent的传递过程学习笔记

在学习自定义控件时,发现SDK中对touch event的描述比较模糊,所以自己写了个demo并结合源代码测试了一下

在View类中,处理TouchEvent的方法有:dispatchTouchEvent和onTouchEvent

在ViewGroup类中处理TouchEvent的方法有:ViewGroup、onInterceptTouchEvent和onTouchEvent

测试布局模型是:

<MyViewGroup>
    <MyView />
</MyViewGroup>

当点击View的时候

情况一:如果所有的处理函数都返回false,TouchEvent的传递路径是:

1) ViewGroup.dispatchTouchEvent-----------------ACTION_DOWN
2) ViewGroup.onInterceptTouchEvent--------------ACTION_DOWN
3) View.dispatchTouchEvent----------------------ACTION_DOWN
4) View.onTouchEvent----------------------------ACTION_DOWN
5) ViewGroup.onTouchEvent-----------------------ACTION_DOWN

而且只会受到ACTION_DOWN事件,不会收到ACTION_UP事件或者其它后续事件

情况二:MyView的onTouchEvent返回true,其它都返回false时,结果跟情况一一样

1) ViewGroup.dispatchTouchEvent-----------------ACTION_DOWN
2) ViewGroup.onInterceptTouchEvent--------------ACTION_DOWN
3) View.dispatchTouchEvent----------------------ACTION_DOWN
4) View.onTouchEvent----------------------------ACTION_DOWN
5) ViewGroup.onTouchEvent-----------------------ACTION_DOWN

情况三:MyView的onTouchEvent和dispatchTouchEvent都返回true,其它返回false

1) ViewGroup.dispatchTouchEvent-----------------ACTION_DOWN
2) ViewGroup.onInterceptTouchEvent--------------ACTION_DOWN
3) View.dispatchTouchEvent----------------------ACTION_DOWN
4) View.onTouchEvent----------------------------ACTION_DOWN

你会发现ViewGroup的onTouchEvent不会收到消息,但是还是收不到ACTION_UP事件

情况四:MyView的onTouchEvent和dispatchTouchEvent都返回true,MyViewGroup的dispatchTouchEvent也返回true的时候:

1) ViewGroup.dispatchTouchEvent-----------------ACTION_DOWN
2) ViewGroup.onInterceptTouchEvent--------------ACTION_DOWN
3) View.dispatchTouchEvent----------------------ACTION_DOWN
4) View.onTouchEvent----------------------------ACTION_DOWN
1) ViewGroup.dispatchTouchEvent-----------------ACTION_UP
2) ViewGroup.onInterceptTouchEvent--------------ACTION_UP
3) View.dispatchTouchEvent----------------------ACTION_UP
4) View.onTouchEvent----------------------------ACTION_UP

这时候就能收到ACTION_UP事件

ViewGroup dispatchTouchEvent(event)传递的主要逻辑的伪码:

private View mMotionTarget;//保存真正处理响应的View
if (action == MotionEvent.ACTION_DOWN) //ACTION_DOWN事件
{
    if (mMotionTarget != null) {
        mMotionTarget = null;
    }
    if (!onInterceptTouchEvent()){ //如果拦截方法返回false,即不拦截
        for (allChild){ //循环所有子View或者ViewGroup
            if (child.dispatchTouchEvent()){ //如果child的dispatchTouchEvent返回true,即处理了事件
                mMotionTarget = child;
                return true; //如果child处理的消息,则直接返回true
            }
        }
    } else { //如果拦截方法返回true,即拦截此事件
        不把此事件传递给child,即child将不会收到此事件
    }
}

if (mMotionTarget == null){
    //调用自己的onTouchEvent方法
    //两种情况会走这个分支:1)ACTION_DOWN事件,child都返回false
    //2)后续事件,并且之前的ACTION_DOWN事件,child都返回false
    return onTouchEvent();
}

//以下是后续事件的处理过程
if (onInterceptTouchEvent()){ //如果事件被拦截
    mMotionTarget.dispatchTouchEvent(ACTION_CANCEL);//给目标child发送cancel事件
    return true;//直接返回
} else {//事件没有被拦截
    return mMotionTarget.dispatchTouchEvent();//把事件交给child处理
}

View的dispatchTouchEvent(event)伪码很简单:

return onTouchEvent();


由此可以看出,要想收到ACTION_DOWN的后续事件的条件是路径上的所有dispatchTouchEvent都得返回true

并且自己的onTouchEvent得返回true,而且路径上没有拦截器拦截事件






转载于:https://my.oschina.net/u/1459779/blog/208672

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值