Android touch 事件的处理流程

1.与 touch 事件相关的主要处理方法是:

    dispatchTouchEvent (onInterceptTouchEvent + onTouchEvent)

    onInterceptTouchEvent 只存在于 ViewGroup 中。

2.在页面,touch事件的传递顺序,从外层到内层依次是 Activity,ViewGroup 和 View。

3.Activity 实际上是以 ViewGroup 的身份来处理事件。逻辑如下。

    //Activiyt 的 dispatchTouchEvent 源码
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

    //window 的 superDispatchTouchEvent 源码
    @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }

    //window 中 DecorView 处理 touch 事件的源码
    private DecorView mDecor;
    private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {

        public boolean superDispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);
        }   
    }

可以看出 decorView 处理 dispatchTouchEvent 依赖于 FrameLyaout 的相应方法。FrameLyaout 本身不处理 touch 事件,最后touch 事件由 FrameLyaout 的父类 ViewGroup 处理。

所以 Activity -> ViewGroup -> View 的层次,实际上可以简化为 ViewGroup -> View。

4.ViewGroup 的 touch 事件处理逻辑如下

//ViewGroup dispatchTouchEvent 方法的逻辑类似于以下代码
public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean result = false;             // 默认状态为没有消费过

    if (!onInterceptTouchEvent(ev)) {   // 如果没有拦截交给子View
        result = child.dispatchTouchEvent(ev);
    }

    if (!result) {                      // 如果事件没有被消费,询问自身onTouchEvent
        result = onTouchEvent(ev);
    }

    return result;
}

 5.View 的 dispatchTouchEvent 方法处理逻辑如下

    //View 的 dispatchTouchEvent 方法的源码逻辑类似于如下代码
    public boolean dispatchTouchEvent(MotionEvent event) {

        if (mOnTouchListener.onTouch(this, event)) {
            result = true;
        }

        if (!result && onTouchEvent(event)) {
            result = true;
        }

        return result;
    }

 

view 的 onTouchEvent 中,只要 clickable 属性为 true,那么其返回值就是 true。只要 view.setOnClickListener(null or not null)执行过,clickable = true。所以只要 view 调用过 setOnClickListener 方法,view 的 dispatchTouchVent 方法的返回值就是 true。

 

6.默认情况的方法调用链如下:

ACTION_DOWN 时

Activity.dispatchTouchEvent -> ViewGroup.dispatchTouchEvent -> ViewGroup.onInterceptTouchEvent(return false)

-> View.dispatchTouchEvent -> View.onTouchEvent(return false) -> View.dispatchTouchEvent (return false)

-> ViewGroup.onTouchEvent(return false) -> ViewGroup.dispatchTouchEvent(return false)

-> Activity.onTouchEvent(return false) -> Activity.dispatchTouchEvent(return false)

 

ACTION_MOVE 和 ACTION_UP 时

由于在 ACTION_DOWN 时 ViewGroup 和 View 处理 touch 事件的方法返回值都是 false,所以 ACTION_MOVE 和 ACTION_UP 就不再经过它们的处理,直接由 Activity 处理

Activity.dispatchTouchEvent -> Activity.onTouchEvent(return false) -> Activity.dispatchTouchEvent(return false)

7.图例

 

最后一图有误。如果 view.onTouch 方法返回 false,还是会经过view.onTouchEvent 方法的。

8.结论

1)touch 事件从父视图向子视图传递。父视图先询问子视图是否处理,如果子视图不处理,则由自己的相关方法处理。

所以,如果父视图没有拦截 touch 事件(onInterceptTouchEvent return false),则子视图的事件处理方法优先。

2)如果子视图不处理 ACTION_DOWN 事件,则 ACTION_MOVE 和 ACTION_UP 事件将不会传递到子视图。

3) onClick 方法是在 ACTION_UP 事件之后被触发。

 

参考 https://blog.csdn.net/u012858313/article/details/54315091

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值