`

浅谈onInterceptTouchEvent、onTouchEvent与onTouch

阅读更多
一、onTouch

onTouch是View中OnTouchListener接口中的方法,处理View及其子类被touch是的事件处理。当然,前提是touch时间能够传递到指定的view。Q1:为什么会传递不到呢?

 
 /**
   * Interface definition for a callback to be invoked when a touch event is
   * dispatched to this view. The callback will be invoked before the touch
   * event is given to the view.
   */
   public interface OnTouchListener {
       /**
         * Called when a touch event is dispatched to a view. This allows listeners to
         * get a chance to respond before the target view.
         *
         * @param v The view the touch event has been dispatched to.
         * @param event The MotionEvent object containing full information about
         *        the event.
         * @return True if the listener has consumed the event, false otherwise.
         */
        boolean onTouch(View v, MotionEvent event);
   }

二、onTouchEvent

onTouchEvent同样也是在view中定义的一个方法。处理传递到view 的手势事件。手势事件类型包括ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL四种事件。

  
/**
    * Implement this method to handle touch screen motion events.
    *
    * @param event The motion event.
    * @return True if the event was handled, false otherwise.
    */
   public boolean onTouchEvent(MotionEvent event) {
    ……
    ……
  }

一旦onTouchEvent方法被调用,并返回true则这个手势事件就结束了,并不会向下传递到子控件。Q2:onTouchEvent什么时候被调用呢?

三、onInterceptTouchEvent

onInterceptTouchEvent是在ViewGroup里面定义的。Android中的layout布局类一般都是继承此类的。onInterceptTouchEvent是用于拦截手势事件的,每个手势事件都会先调用onInterceptTouchEvent。

 
 public boolean onInterceptTouchEvent(MotionEvent ev) {
           return false;
   }

此方法返回false,则手势事件会向子控件传递;返回true,则调用onTouchEvent方法。

onInterceptTouchEvent()用于处理事件并改变事件的传递方向。返回值为false时事件会传递给子控件的onInterceptTouchEvent();
返回值为true时事件会传递给当前控件的onTouchEvent(),而不在传递给子控件,这就是所谓的Intercept(截断)。

onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1.       down事件首先会传递到onInterceptTouchEvent()方法
2.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4.       如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5.       如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。


http://2528.iteye.com/blog/1056731

onInterceptTouchEvent和onTouchEvent调用关系详解
http://www.eoeandroid.com/thread-178659-1-1.html
return true和return false,代表的是是否消费完该事件,也就是该事件是否会继续传递给下层或者上层组件继续处理。return true代表消费完不会继续传递,return false代表没有消费完将会继续传递。

如果没有onInterceptTouchEvent,只考虑onTouchEvent的话,比较容易分析和理解。假如有三层布局结构,linearLayout1,linearLayout2,textView,从前到后是包含的关系。那么下面分情况说明。
1.如果它们的onTouchEvent都返回false的话,DOWN事件会自上而下(textView位于最上层)依次传递,最终都没有消费完此事件,都只会进入onTouchEvent方法一次并且MotionEvent的action为MotionEvent.ACTION_DOWN,move和up等事件不会继续处理。
2.如果textView的onTouchEvent返回true,表示textView消费了此事件,不会传给父组件linearLayout2和linearLayout1了,并且还会继续处理move和up等事件。
3.linearLayout2和linearLayout1的onTouchEvent返回true和上面的情况一样,都不会继续传给父容器而且本身继续处理move和up等事件。
OK,这种情况还是比较容易理解的。

下面加入onInterceptTouchEvent。
onInterceptTouchEvent只有ViewGroup才会有,用于在进入自身onTouchEvent或者子组件onTouchEvent之前处理事件。注意onTouch是自上而下传递,而onInterceptTouch却是由下而上传递的。来了一个DOWN事件,首先进入的必然是最底层的viewGroup的onInterceptTouchEvent方法,然后根据return的值进入自身或者子组件的onTouch事件,当然如果子组件也是viewgroup的话,在进入子组件的onTouch之前也会进入子组件的onInterceptTouchEvent方法。
下面也分几种情况介绍:
1.当onInterceptTouchEvent返回false时,表示没有消费完此事件,会继续传递个子组件的onTouch继续处理。注意这种情况不会就不会传递给这个ViewGroup自身的onTouch事件处理了。这和onTouch如果返回false,后续的move、up等事件都不会继续处理了可以做同样理解。
2.当onInterceptTouchEvent返回true时,表示消费完此事件,或者说将在此组件上消费该事件。这种情况该事件会传递给ViewGroup自身的onTouch事件去处理,而不会传递给子组件的onTouch方法了。
由此可以总结,onInterceptTouchEvent返回值只是决定了是要把事件传递给自身的onTouch事件还是传递给子组件的onTouch事件。返回false表示没有消费完将传递个子组件的onTouch方法,返回true表示自身消费此事件,将传递给自身的onTouch方法而不会传递给子组件的onTouch方法了。
分享到:
评论
4 楼 yangmaolinpl 2017-03-02  
希望有表例子更好。。。,不过也看明白了。
3 楼 naifei1234 2013-10-15  
                         
2 楼 lenomon 2012-04-02  
1 楼 进阶兄 2011-09-06  
谢谢,获益匪浅

相关推荐

Global site tag (gtag.js) - Google Analytics