美文网首页
Android事件分发

Android事件分发

作者: 葫芦娃大战屎壳郎 | 来源:发表于2019-06-03 10:46 被阅读0次

    一些疑问:

    • dispatchTouchEvent,onTouchEvent,OnTouchListener.onTouch之间的关系
    • 事件分发流程
    • 父控件如何拦截事件
    • 嵌套滑动原理

    主要内容

    • Activity 事件分发
    • View事件分发
    • ViewGroup 事件分发
    • NestedScrolling机制

    Activity 事件分发

    对于Activity的事件分发比较简单,只要搞清楚dispatchTouchEvent方法的调用关系,如何将事件传递到DecorView


    image

    View 事件分发

    严格的讲View的dispatchTouchEvent不算事件分发,因为View没有子View,只能说是对事件处理流程

    View.dispatchTouchEvent(MotionEvent event)

    1. 先调用mOnTouchListener.onTouch方法(如果设置了OnTouchListener)
    2. 如果上面onTouch方法返回true,说明事件被消耗,处理结束,返回true
    3. 如果第一步onTouch方法返回false,或者没有设置OnTouchListener,才会调用onTouchEvent,并返回onTouchEvent的结果

    整个View.dispatchTouchEvent就这么简单,下面看下onTouchEvent方法

    View.onTouchEvent(MotionEvent event)

    onTouchEvent主要处理了OnClickListener和OnLongClickListener

    • ACTION_DOWN:调用checkForLongClick()方法添加延迟事件
    • ACTION_MOVE:调用了removeLongPressCallback()移除长按延迟事件
    • ACTION_UP:调用performClickInternal()触发OnClickListener(前提是OnLongClickListener没有触发)

    ViewGroup 事件分发

    • 首先调用onInterceptTouchEvent方法判断是否拦截事件(默认返回false不拦截),调用了requestDisallowInterceptTouchEvent()方法后也不拦截事件,如下代码:
    if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    if (!disallowIntercept) {
        intercepted = onInterceptTouchEvent(ev);
        ev.setAction(action); // restore action in case it was changed
    } else {
        intercepted = false;
    }
    
    • 如果不拦截事件,就遍历childView查找对应触摸位置上且可见的子View,如果找到了就调用child.dispatchTouchEvent,如果没找到或者child.dispatchTouchEvent返回false则会继续调用super.dispatchTouchEvent(event)将事件分发给自己
    • 如果拦截事件,调用super.dispatchTouchEvent(event)分发事件给自己,即从View那里继承而来的dispatchTouchEvent方法
    image

    相关文章

      网友评论

          本文标题:Android事件分发

          本文链接:https://www.haomeiwen.com/subject/ginqxctx.html