Android 事件处理机制

前言

在Android中,View视图是以树状结构来展示的,一个ViewGroup既可以可以装入若干个View,也可以在ViewGroup里面再嵌套若干个ViewGroup,那么对于一个事件,子View或者父ViewGroup都可能要处理,因此就须有有一些“规则”来定义这个事件处理机制。

MotionEvent事件

在手指接触屏幕后所产生的一系列事件中,典型的事件类型有如下几种:

ACTION_DOWN  ----- 手指刚接触屏幕
ACTION_MOVE   ----- 手指在屏幕上移动
ACTION_UP        ----- 手指从屏幕上松开的一瞬间

正常情况下,一次手指触碰屏幕的行为会触发一系列触摸事件,考虑如下几种情况:

点击屏幕后立即松开,事件顺序为 ACTION_DOWN -> ACTION_UP
点击屏幕后滑动一会再松开,事件顺序为 ACTION_DOWN -> ACTION_MOVE ->...-> ACTION_MOVE -> ACTION_UP

获取点击事件发生的x坐标和y坐标

getX/getY:返回的是相对于当前View左上角的x和y坐标

getRawX/getRawY:返回的是相对于手机屏幕左上角的x和y坐标

涉及到事件处理过程的有三个重要的方法

   /**
     * 对事件进行分发
     * Activity, ViewGroup, View都有此方法
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    /**
     *用来过滤事件的,即进行事件的拦截,也就是是否要向下传递事件
     * 只有ViewGroup有
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev);
    }

    /**
     * 最终用来处理事件的
     *Activity, ViewGroup, View都有此方法
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }

事件处置过程

当事件传递到一个ViewGroup上面时,ViewGroup会触发dispatchTouchEvent方法,随后调用onInterceptTouchEvent方法确认是否拦截此事件,最后如果事件是自己来处理的话,则调用onTouchEvent方法。
  在ViewGroup类中,onInterceptTouchEvent方法总是返回false,表示默认是不拦截事件的,除非去重写ViewGroup类来返回true。而onTouchEvent方法的返回值表示是否消费(返回true则消费)此事件,消费的意思就是说ViewGroup自己处理了这个事件,不再传递到上一层的onTouchEvent去。
  而在View中,与ViewGroup相比,同样有dispatchTouchEvent方法和onTouchEvent方法。但是没有onInterceptTouchEvent这个方法,因为在一个View中,已经是View树的叶子节点,它没有下一级的视图嵌套,所以不需要决定是否拦截事件,它自己就可以处理事件了。
  在View类中,只要该View是可以点击的,那么默认都会在onTouchEvent返回true,表示自己消费了这个事件,不再传递到上一级ViewGroup去。

注意

如果在同一个事件序列里面,如果ACTION.DOWN事件不被这个View做出消耗,则后面陆续的事件序列则不会传递到这个View来。
注意事件拦截和事件消费是两回事,事件拦截说的是不把事件发给下一级View,而事件消费说的是处理完这个事件还要不要让上一级也处理,如果消费了事件那么就不会再让上一级处理这个事件

你可能感兴趣的:(Android 事件处理机制)