看过网上总结过很多帖子,但是发现还不算是很细致,自己最近研究这一部分,分享一下学习心得。
dispatchTouchEvent负责分发事件,源码如下:
if (onFilterTouchEventForSecurity(event)) { //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { result = true; } if (!result && onTouchEvent(event)) { result = true; } }
注意到在dispatchTouchEvent中会观察touchListener是否为空,如果不为空讲执行他的ontouch方法。
1 所以对于ViewGroup,他的执行顺序是:dispatchTouchEvent->onTouch->onInterceptTouchEvent->onTouchEvent。需要注意的是如果在onTouch事件中返回了true,那么将不会再执行onTouchEvent事件。(也不会执行onClick与onLongClick事件,因为这两个事件是写在onTouch事件当中的)
2onInterceptTouchEvent是ViewGroup独有的方法,他的down事件比较特殊,需要注意,如果down事件返回值为true,那么事件不会再传给他的子View,而是到ViewGroup截止了,事件交给ViewGroup的onTouchEvent事件进行处理。并且后续的move,up事件不再走onInterceptTouchEvent,直接交给ViewGroup的ouTouchEVent处理,可以理解为onInterceptTouchEvent有记忆功能。
3再看下onTouchEvent的down,up事件。他们跟onClick与onLongClick有很大的联系,onLongClick事件在down事件后触发,开始计时,当UP事件响应后,会根据持续事件判断,是否触发onLongClick事件,onClick事件在UP事件后触发,并且在onLongClick事件后触发(假如onLongClick返回true,onClick不会执行)。
@Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ System.out.println("MyButton-----Down"); return super.onTouchEvent(event); } if(event.getAction() == MotionEvent.ACTION_UP){ System.out.println("MyButton-----UP"); return true; } return super.onTouchEvent(event); }
上图,因为down事件交给父类处理,因此会执行onLongClick事件,但是UP中返回true,所以并不会执行onClick。
@Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ System.out.println("MyButton-----Down"); return false; } if(event.getAction() == MotionEvent.ACTION_UP){ System.out.println("MyButton-----UP"); return super.onTouchEvent(event); } return super.onTouchEvent(event); }
如果将down事件的返回值false,那么up,move事件就不再走onTouchEvent
@Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ System.out.println("MyButton-----Down"); return true; } if(event.getAction() == MotionEvent.ACTION_UP){ System.out.println("MyButton-----UP"); return super.onTouchEvent(event); } return super.onTouchEvent(event); }
如果将down事件返回值true,那么会执行down与up事件,而onClick不会执行,因为onClick同样要求父类进行处理down与up操作。
@Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ System.out.println("MyButton-----Down"); return super.onTouchEvent(event); } if(event.getAction() == MotionEvent.ACTION_UP){ System.out.println("MyButton-----UP"); return super.onTouchEvent(event); } return super.onTouchEvent(event); }<pre name="code" class="java">这样 down up onclick longclick都会执行
tv.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { System.out.println("longclick"); return false; } }); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { System.out.println("onclick"); } });onLongClick如果返回false,那么onClick会执行,如果true,则不会执行。