自定义view的事件分发

android中的每个ViewGroup的子类都具有三个和TouchEvent相关的方法:

1.public boolean dispatchTouchEvent(MotionEvent event)              这个方法用来分发TouchEvent

2.public boolean onInterceptTouchEvent(MotionEvent event)         这个方法用来拦截TouchEvent

3.public boolean onTouchEvent(MotionEvent event)                        这个方法用来处理TouchEvent

注意:不是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。

举一个简单的例子:(一个activity,布局中有一个button)

对button进行监听

 button.setOnClickListener(new OnClickListener() {
     @Override
   public void onClick(View v) {
        Log.d("TAG", " onClick");
     }
});


button添加一个touch事件

 button.setOnTouchListener(new OnTouchListener() {
     @Override
    public boolean onTouch(View v, MotionEvent event) {
         Log.d("TAG", "onTouch " + event.getAction());
         return false;
     }
 });

执行结果如下:
onTouch  0  相当与down
onTouch  1  相当于up
onClick     点击事件
由上面的结果可以看出来:事件传递的顺序是先经过onTouch,再传递到onClick
当onTouch return false说明你还没消费onTouch事件,在执行完你onTouch里面的代码之后,onTouch事件并没有结束
当onTouch return true时说明此次事件被onTouch给消费掉了,不会继续向下传递了

接着看dispatchTouchEvent的源码

    /**
      * Pass the touch screen motion event down to the target view, or this
      * view if it is the target.
      * @param event The motion event to be dispatched.
      * @return True if the event was handled by the view, false otherwise.
      */
     public boolean dispatchTouchEvent(MotionEvent event) {
         if (!onFilterTouchEventForSecurity(event)) {
             return false;
        }
         if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
                 mOnTouchListener.onTouch(this, event)) {
            return true;
         }
         return onTouchEvent(event);
    }
1. OnTouchListener是在setOnTouchListener方法中设置的,事实上就是我们刚才在Activity中设置的setOnTouchListener,也就是说只要我们给控件注册了touch事件,mOnTouchListener就一定被赋值了

2.第二个条件是判断控件是否是使能的,按钮默认即使Enabled,所以为true

3.第三个条件是关键,该条件会回调控件注册touch事件时的onTouch方法,这里关键就是看onTouch方法执行的返回值

还有一点要题型的是Touch事件的层级传递。如果给一个控件注册了touch事件,每次点击它的时候都会触发一系列ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件.如果你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action。

猜你喜欢

转载自blog.csdn.net/xifei66/article/details/54583247