Android 事件分发笔记 二

218 阅读2分钟

事件分发流程 : Activity --> ViewGroup --> View

当一个点击事件触发后,首先传入activity 然后传入viewgroup 最终传入view

1.activity对点击事件的处理

首先将相关方法列出

/**
 * Called to process touch screen events.  You can override this to
 * intercept all touch screen events before they are dispatched to the
 * window.  Be sure to call this implementation for touch screen events
 * that should be handled normally.
 *
 * @param ev The touch screen event.
 *
 * @return boolean Return true if this event was consumed.
 */
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    
    if (getWindow().superDispatchTouchEvent(ev)) {
        //跳转到下面  一
        return true;
    }
    //如果上面跳过 即getWindow().superDispatchTouchEvent(ev)返回false
    // 跳转下面 三
    return onTouchEvent(ev);
}


一:
/**
  * getWindow().superDispatchTouchEvent(ev)
  * getWindow() = 获取Window类的对象
  * Window 由 PhoneWindow类实现
  * PhoneWindow类实现抽象方法
  */
  @Override
  public boolean superDispatchTouchEvent(MotionEvent event) {
      //跳转到下面 二
      return mDecor.superDispatchTouchEvent(event);
      // mDecor = 顶层View(DecorView)的实例对象
  }
  
  
  二: 
  /**
  *mDecor.superDispatchTouchEvent(event)
  *View(DecorView)
  *DecorView类是PhoneWindow类的一个内部类
  *DecorView继承自FrameLayout,是所有界面的父类
  *FrameLayout是ViewGroup的子类,DecorView的间接父类 = ViewGroup
  */
  public boolean superDispatchTouchEvent(MotionEvent event) {

  return super.dispatchTouchEvent(event);
  // 调用ViewGroup的dispatchTouchEvent()
  //将事件传递到ViewGroup去处理
  }
  
  三:
  //走到这一步说明 时间没有被任何view 进行处理 
  public boolean onTouchEvent(MotionEvent event) {
      // 跳转下面 四
    if (mWindow.shouldCloseOnTouch(this, event)) {
        finish();
        // 走到这里说明点击是是无效区域
        return true;
    }
    //走到这里说明点击的是正常区域  一般都走到这里
    return false;
}

四:
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
    final boolean isOutside =
            event.getAction() == MotionEvent.ACTION_UP && isOutOfBounds(context, event)
            || event.getAction() == MotionEvent.ACTION_OUTSIDE;
    if (mCloseOnTouchOutside && peekDecorView() != null && isOutside) {
        //返回了true 说明事件是触发在手机屏幕外面 
        return true;
    }
     //false 说明事件是触发在手机屏幕内
    return false;
}

综上情况当一个时间产生时,在activity的流程为:

开始(碰触到屏幕)--> activity的dispatchTouchEvent(MotionEvent ev) --> window的 superDispatchTouchEvent(MotionEvent event) --> DecorView的 superDispatchTouchEvent(MotionEvent event) -->ViewGroup的 dispatchTouchEvent()

dispatchTouchEvent() 返回ture --> 事件结束

dispatchTouchEvent() 返回false --> activity 的onTouchEvent(MotionEvent event) --> window 的shouldCloseOnTouch(Context context, MotionEvent event) --> 事件结束