[Learn]Android touch事件传递机制

来源:互联网 发布:售后服务网络 编辑:程序博客网 时间:2024/06/07 21:17

Android touch事件传递机制

Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件实际上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。ViewGroup的相关事件有三个:    onInterceptTouchEvent    dispatchTouchEvent    onTouchEventView的相关事件只有两个:    dispatchTouchEvent    onTouchEvent

这里写图片描述

当一个Touch事件(触摸事件为例)到达根节点,即Acitivty的ViewGroup时,它会依次下发,下发的过程是调用子View(ViewGroup)的dispatchTouchEvent方法实现的。简单来说,就是ViewGroup遍历它包含着的子View,调用每个View的dispatchTouchEvent方法,而当子View为ViewGroup时,又会通过调用ViwGroup的dispatchTouchEvent方法继续调用其内部的View的dispatchTouchEvent方法。上述例子中的消息下发顺序是这样的:①-②-⑤-⑥-⑦-③-④。dispatchTouchEvent方法只负责事件的分发,它拥有boolean类型的返回值,当返回为true时,顺序下发会中断。在上述例子中如果⑤的dispatchTouchEvent返回结果为true,那么⑥-⑦-③-④将都接收不到本次Touch事件。

/**     * ViewGroup     * @param ev     * @return     */    public boolean dispatchTouchEvent(MotionEvent ev){        ....//其他处理,在此不管        View[] views=getChildView();        for(int i=0;i<views.length;i++){           //判断下Touch到屏幕上的点在该子View上面             if(...){            if(views[i].dispatchTouchEvent(ev))              return true;             }        }        ...//其他处理,在此不管    }    /**     * View     * @param ev     * @return     */    public boolean dispatchTouchEvent(MotionEvent ev){        ....//其他处理,在此不管        return false;    }

在此可以看出,ViewGroup的dispatchTouchEvent是真正在执行“分发”工作,而View的dispatchTouchEvent方法,并不执行分发工作,或者说它分发的对象就是自己,决定是否把touch事件交给自己处理,而处理的方法,便是onTouchEvent事件,事实上子View的dispatchTouchEvent方法真正执行的代码是这样的

/**     * View     * @param ev     * @return     */    public boolean dispatchTouchEvent(MotionEvent ev){        ....//其他处理,在此不管        return onTouchEvent(event);    }

一般情况下,我们不该在普通View内重写dispatchTouchEvent方法,因为它并不执行分发逻辑。当Touch事件到达View时,我们该做的就是是否在onTouchEvent事件中处理它。

那么,ViewGroup的onTouchEvent事件是什么时候处理的呢?当ViewGroup所有的子View都返回false时,onTouchEvent事件便会执行。由于ViewGroup是继承于View的,它其实也是通过调用View的dispatchTouchEvent方法来执行onTouchEvent事件。

在目前的情况看来,似乎只要我们把所有的onTouchEvent都返回false,就能保证所有的子控件都响应本次Touch事件了。但必须要说明的是,这里的Touch事件,只限于Acition_Down事件,即触摸按下事件,而Aciton_UP和Action_MOVE却不会执行。事实上,一次完整的Touch事件,应该是由一个Down、一个Up和若干个Move组成的。Down方式通过dispatchTouchEvent分发,分发的目的是为了找到真正需要处理完整Touch请求的View。当某个View或者ViewGroup的onTouchEvent事件返回true时,便表示它是真正要处理这次请求的View,之后的Aciton_UP和Action_MOVE将由它处理。当所有子View的onTouchEvent都返回false时,这次的Touch请求就由根ViewGroup,即Activity自己处理了。

View mTarget=null;//保存捕获Touch事件处理的View    public boolean dispatchTouchEvent(MotionEvent ev) {        //....其他处理,在此不管        if(ev.getAction()==KeyEvent.ACTION_DOWN){            //每次Down事件,都置为Null            if(!onInterceptTouchEvent()){            mTarget=null;            View[] views=getChildView();            for(int i=0;i<views.length;i++){                if(views[i].dispatchTouchEvent(ev))                    mTarget=views[i];                    return true;            }          }        }        //当子View没有捕获down事件时,ViewGroup自身处理。这里处理的Touch事件包含Down、Up和Move        if(mTarget==null){            return super.dispatchTouchEvent(ev);        }        //...其他处理,在此不管        if(onInterceptTouchEvent()){         //...其他处理,在此不管             }//这一步在Action_Down中是不会执行到的,只有Move和UP才会执行到。        return mTarget.dispatchTouchEvent(ev);    }
原创粉丝点击