事件分发

ViewRootImpl/DecorView/Activity/Window/DecorView

事件由 ViewRootImpl 分发,会先分发到 DecorView。

//ViewRootImpl.java
private int processPointerEvent(QueuedInputEvent q) {
            final MotionEvent event = (MotionEvent)q.mEvent;
            ...
            //关键点:mView分发Touch事件,mView就是DecorView
            boolean handled = mView.dispatchPointerEvent(event);
            maybeUpdatePointerIcon(event);
            maybeUpdateTooltip(event);
            ...
       }
 // View.java
 public final boolean dispatchPointerEvent(MotionEvent event) {
        if (event.isTouchEvent()) {
            //分发Touch事件
            return dispatchTouchEvent(event);
        } else {
            return dispatchGenericMotionEvent(event);
        }
    }

Window.Callback都被Activity和Dialog实现,所以变量cb可能就是Activity和Dialog。

Activity

Window

DecorView

ViewGroup

View

onTouchEvent(event) 中会调用onClick 和 onLongClick。

调用onClick 是在UP事件时,检查是否clickable以及是否设置监听;

调用onLongClick 是在Down 事件时,发出一个延时任务,如果任务执行时还是按下状态,就执行难onLongClick.

//todo 源码

多点触控

处理POINTER_DOWN 和POINTER_UP,进行指针处理。

区分 actionIndex(pointerIndex)/ pointerId.

滑动冲突

父View根据需要重写 onIntercept 或者子View根据需要调用父View的requestDisallowIntercept禁用父View对事件的拦截。

requestDisallowIntercept 会向上传递。

相关问题

事件传递大体过程:Activity--> Window-->DecorView --> View树从上往下,传递过程中谁想拦截就拦截自己处理。MotionEvent是Android中的点击事件。主要事件类型:

  • ACTION_DOWN 手机初次触摸到屏幕事件

  • ACTION_MOVE 手机在屏幕上滑动时触发,会回调多次

  • ACTION_UP 手指离开屏幕时触发

需要关注的几个方法。

  • dispatchTouchEvent(event);

  • onInterceptTouchEvent(event);

  • onTouchEvent(event);

上面3个方法可以用以下伪代码来表示其关系:

如何解决View的滑动冲突?

父类根据需要重写 onIntercept 或者子View根据需要调用requestDisallowIntercept

onTouch()、onTouchEvent()和onClick()关系?

如果一个View需要处理事件,它设置了OnTouchListener,那么OnTouchListener的onTouch方法会被回调。如果onTouch返回false,则onTouchEvent会被调用,反之不会。在onTouchEvent方法中,事件为Action.UP的时候会回调OnClickListener的onClick方法,可见OnClickListener的优先级很低。

防止短时间内重复点击

通过在对比两次ACTION_DOWN事件之间的时间间隔是否小于最小间隔,如果小于直接忽略。

视应用范围,这段逻辑可以放在View/ViewGroup/Activity 中 。

相关链接

安卓自定义View进阶-MotionEvent详解

玩安卓|每日一问

玩安卓|每日一问:多指触控

安卓自定义View进阶-多点触控详解

事件分发和NestedScrolling(二)

最后更新于

这有帮助吗?