龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 移动开发 > Android开发 >

Android Touch事件分发过程详解(5)

时间:2014-09-12 02:14来源:网络整理 作者:网络 点击:
分享到:
View的Touch事件分发 /** * 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

View的Touch事件分发

/** 
 * 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); 
} 

该函数中,首先判断该事件是否符合安全策略,然后判断该view是否是enable的 ,以及是否设置了Touch Listener,mOnTouchListener即我们通过setOnTouchListener设置的。

/** 
 * Register a callback to be invoked when a touch event is sent to this view. 
 * @param l the touch listener to attach to this view 
 */ 
public void setOnTouchListener(OnTouchListener l) { 
  mOnTouchListener = l; 
} 

如果mOnTouchListener.onTouch(this, event)返回false则继续执行onTouchEvent(event);如果mOnTouchListener.onTouch(this, event)返回true,则表示该事件被消费了,不再传递,因此也不会执行onTouchEvent(event)。这也验证了我们上文中留下的场景2,当onTouch函数返回true时,点击按钮,但我们的点击事件没有执行。那么我们还是先来看看onTouchEvent(event)函数到底做了什么吧。

/** 
 * 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) { 
  final int viewFlags = mViewFlags; 
 
  if ((viewFlags & ENABLED_MASK) == DISABLED)    // 1、判断该view是否enable 
    // 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)) // 2、是否是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))   // post 
                performClick();     // 3、点击事件处理 
              } 
            } 
          } 
 
          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; 
} 

精彩图集

赞助商链接