Android触摸事件传递机制

点击事件分发

  • ACTION_DOWN事件触发时,会从Activity -> PhoneWindow -> DecorView -> ViewGroup -> View顺序,逐层调用对应的dispatchTouchEvent方法分发。
  • 在View的dispatchTouchEvent中,常理会调用onTouchEvent,在onTouchEvent方法中,ACTION_DOWN时,会检查是否是长按,时长超过500毫秒则是长按;在ACTION_UP时,会调用performOnClickInteral,依次调用onClick(),响应点击事件。如果重写onTouch()方法,返回true,则View的dispatchTouchEvent中,有一个if判断条件成立,会将boolean局部变量result置true,那么接下来一个if判断中,该result为true,就不会调用onTouchEvent方法,因此该次触摸事件则消费结束,不会再响应onLongClick和onClick。如果重写onLongClick()方法,返回true,则在onTouchEvent方法中,ACTION_DOWN时,检查是长按后,会调用onLongClick(),响应长按事件,该方法返回true后,会将mHasPerformedLongPress代表是否执行了长按事件的boolean值置true;在ACTION_UP时,调用performOnClickInteral前,会先判断mHasPerformedLongPress,为true,则不调,为false,才调用。因此,重写onLongClick()方法,返回true时,不会再响应onClick。

点击事件传递过程:

  1. ACTION_DOWN事件,Viewgroup的dispatchTouchEvent分发事件,onInterceptTouchEvent拦截事件,默认不拦截,继续向下分发给子View,子View的dispatchTouchEvent分发事件,传给子View的onTouchEvent,若返回true消费,则后面的ACTION_MOVE和ACTION_UP事件按顺序继续分发传递。
  2. 事件传给子View的onTouchEvent时,子View返回false,不消费事件,则事件回传给ViewGroup的onTouchEvent来消费,以后的时间会按照ViewGoup的dispatchTouchEvent到onTouchEvent来传递消费。
  3. 当ViewGroup的onInterceptTouchEvent拦截事件后,则会传递给ViewGroup的onToucnEvent消费,以后的其他事件也会按照ViewGoup的dispatchTouchEvent到onTouchEvent来传递消费,不会再传给子View。

解决触摸事件冲突:

  • 外部拦截。ViewGroup重写onInterceptTouchEvent方法,默认不拦截,事件往下分发给子View,若返回true,则拦截此次事件,将事件传给ViewGroup的onTouchEvent处理。
  • 内部拦截。重写子View的dispatchTouchEvent方法,方法中调用getParent().requestDisallowInterceptTouchEvent(true)方法,传true则代表不希望ViewGroup拦截事件,传false则代表希望ViewGroup拦截事件。
  • 内部拦截。子View重写onTouchEvent方法,返回true,则子View消费该次事件,返回false,该次事件返回给ViewGroup的onTouchEvent处理。

你可能感兴趣的:(Android触摸事件传递机制)