美文网首页
Android事件分发机制和触摸反馈

Android事件分发机制和触摸反馈

作者: Mr_丁先森 | 来源:发表于2018-09-30 15:09 被阅读0次

    前言

    首先,Android系统为什么会定义一套事件分发机制?
    其实很简单,因为我们的布局里面View,ViewGroup是树状结构,一组事件顺序流过来,到底是View处理还是ViewGroup处理,都是在Android 事件分发机制下运行的,有了Android事件分发机制我们可以有效避免事件冲突,或者是可以很方便的自定义触摸反馈。


    Android事件分发机制

    机制下的核心类

    public final class MotionEvent extends InputEvent implements Parcelable {
    
        /**
         * Constant for {@link #getActionMasked}: A pressed gesture has started, the
         * motion contains the initial starting location.
         * <p>
         * This is also a good time to check the button state to distinguish
         * secondary and tertiary button clicks and handle them appropriately.
         * Use {@link #getButtonState} to retrieve the button state.
         * </p>
         */
        public static final int ACTION_DOWN             = 0;
    
        /**
         * Constant for {@link #getActionMasked}: A pressed gesture has finished, the
         * motion contains the final release location as well as any intermediate
         * points since the last down or move event.
         */
        public static final int ACTION_UP               = 1;
    
        /**
         * Constant for {@link #getActionMasked}: A change has happened during a
         * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}).
         * The motion contains the most recent point, as well as any intermediate
         * points since the last down or move event.
         */
        public static final int ACTION_MOVE             = 2;
    
        /**
         * Constant for {@link #getActionMasked}: The current gesture has been aborted.
         * You will not receive any more points in it.  You should treat this as
         * an up event, but not perform any action that you normally would.
         */
        public static final int ACTION_CANCEL           = 3;
    
          //省略非核心代码
          ......
    }
    
    

    机制下的核心方法

    • dispatchTouchEvent()
    • onInterceptTouchEvent()
    • onTouchEvent()

    机制的关键知识点

    • Activity最顶层的Window是PhoneWindow,PhoneWindow最顶层的View是DecorView,DecorView是继承FrameLayout,DecorView下面是一个LinearLayout,
      LinearLayout下面有两个子View,两个子View都是继承FrameLayout。
    • 一个clickable或者longClickable的View会永远消费Touch事件。
    • 长按事件是在ACTION_DOWN事件中执行的,要想执行长按事件该View必须设置longClickable,然后通过OnLongClickListener回调给上层应用处理,期间不能产生ACTION_MOVE事件。
    • 点击事件是在ACTION_UP事件中执行的,前提是消费了ACTION_DOWN事件,并且没有设置OnLongClickListener的情况下,如设置了OnLongClickListener的情况,则必须使onLongClick()返回false。
    • 如果View设置了onTouchListener了,并且onTouch()方法返回true,则不执行View的onTouchEvent()方法,也表示View消费了Touch事件,返回false则继续执行onTouchEvent()。
    • 事件流分发过程中,子View如果处理了ACTION_DOWN事件,但是后面的事件流里面的事件被父View,在onInterceptTouchEvent中被拦截,那么父View 就接管后面的事件流,并且向处理了ACTION_DOWN的子View发送一个ACTION_CANCEL事件。

    触摸反馈

    • 对于触摸反馈,一般是我们在自定义View的时候,在Android事件分发机制下,来使用,比如我们需要在自定义的View里面做自己的触发算法,这个时候需要重写View的onTouchEvent方法,在里面写上你的触摸反馈算法,并返回 true(关键是 ACTION_DOWN 事件时返回 true。
    • 如果是会发生触摸冲突的 ViewGroup,还需要重写 onInterceptTouchEvent(),在事件流开始时返回 false,并在确认接管事件流时返回一次 true,以实现对事件的拦截。
    • 当子 View 临时需要父View 拦截事件流时,可以调用父 View 的 requestDisallowInterceptTouchEvent() ,通知父 View 在当前事件流中不再尝试通过 onInterceptTouchEvent() 来拦截。

    相关文章

      网友评论

          本文标题:Android事件分发机制和触摸反馈

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