Android事件分发机制
这篇文章的思路源于以为大牛的博客,自己按照自己的思路写在这里,或许自己的东西更容易看懂把。
一个Button如果都注册了onTouch 和 onClick事件 ,首先响应的是onTouch事件,然后是onClick事件。 当我们触碰了一个控件,就会首先去调用该控件布局的dispatchTouchEvent方法,然后再才调用该控件的dispatchTouchEvent方法、 public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null && ( mViewFlags & ENABLED_MASK) == ENABLED && mOnTouchListener.onTouch(this, event)) { return true ; } return onTouchEvent(event); } 该方法首先三个判断: 1.mOnTouchListener != null mOnTouchListener 被赋值的地方在这里,实际上就是我们在注册事件监听时赋值: public void setOnTouchListener(OnTouchListener l) { mOnTouchListener = l; } 2.(mViewFlags & ENABLED_MASK ) == ENABLED 控件是否可以点击? 3.mOnTouchListener .onTouch(this, event) 其实这里是回调了onTouch()方法,如果onTouch方法返回true, 则条件判断为true,不再继续往下执行,否则为false,会继续往下执行. || || || || public boolean onTouchEvent (MotionEvent event) { final int viewFlags = mViewFlags; if ((viewFlags & ENABLED_MASK) == DISABLED) { // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE )); } if (mTouchDelegate != null) { if (mTouchDelegate .onTouchEvent(event)) { return true ; } } ------------------------------从这行开始可以看出,后面的就是该行为的动作判断了----------------------- if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE )) { switch (event.getAction()) { case MotionEvent.ACTION_UP: boolean prepressed = (mPrivateFlags & PREPRESSED) != 0; if ((mPrivateFlags & PRESSED) != 0 || prepressed) { // take focus if we don't have it already and we should in // touch mode. boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); } if (!mHasPerformedLongPress ) { // This is a tap, so remove the longpress check removeLongPressCallback(); // Only perform take click actions if we were in the pressed state if (!focusTaken) { // Use a Runnable and post this rather than calling // performClick directly. This lets other visual state // of the view update before click actions start. if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick )) { performClick(); } } } if (mUnsetPressedState == null) { mUnsetPressedState = new UnsetPressedState(); } if (prepressed) { mPrivateFlags |= PRESSED ; refreshDrawableState(); postDelayed( mUnsetPressedState, ViewConfiguration.getPressedStateDuration()); } else if (!post(mUnsetPressedState)) { // If the post failed, unpress right now mUnsetPressedState.run(); } removeTapCallback(); } break; case MotionEvent.ACTION_DOWN: if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } mPrivateFlags |= PREPRESSED ; mHasPerformedLongPress = false ; postDelayed( mPendingCheckForTap, ViewConfiguration.getTapTimeout()); break; case MotionEvent.ACTION_CANCEL: mPrivateFlags &= ~PRESSED; refreshDrawableState(); removeTapCallback(); break; case MotionEvent.ACTION_MOVE: final int x = (int) event.getX(); final int y = (int) event.getY(); // Be lenient about moving outside of buttons int slop = mTouchSlop ; if ((x < 0 - slop) || (x >= getWidth() + slop) || (y < 0 - slop) || (y >= getHeight() + slop)) { // Outside button removeTapCallback(); if ((mPrivateFlags & PRESSED) != 0) { // Remove any future long press/tap checks removeLongPressCallback(); // Need to switch from pressed to not pressed mPrivateFlags &= ~PRESSED; refreshDrawableState(); } } break; } return true ;这一句无论什么情况下都会执行 } return false ; } --------------看重点:当我们手指抬起的时候,会执行到performClick();这个方法里面去。然后回去执行onClick事件 || || || || public void setOnClickListener(OnClickListener l) { if (!isClickable()) { setClickable( true); } mOnClickListener = l; } public boolean performClick() { sendAccessibilityEvent(AccessibilityEvent. TYPE_VIEW_CLICKED); if (mOnClickListener != null) { playSoundEffect(SoundEffectConstants. CLICK); mOnClickListener.onClick( this); return true ; } return false ; } || || || || 分析一下:通常情况下,我们用到onTouch事件时,会将 if (event.getAction() == MotionEvent. ACTION_DOWN ){} else if(else if (event.getAction() == MotionEvent. ACTION_UP){} 两个动作拿出来,当前者返回false,则后者就不会执行。