• Android Touch事件相关源码【Android SourceCode 2.3.6】


    2018-05-31 17:23:46

    Note: 这里的源码来自Android 2.3.6,这个版本的代码比较简单,适合理解Touch事件的传递原理。后续版本源码复杂了很多,但是原理都是类似的。

    2个方法源码较多,在这里记录下。

    View.java

      1  /**
      2      * Implement this method to handle touch screen motion events.
      3      *
      4      * @param event The motion event.
      5      * @return True if the event was handled, false otherwise.
      6      */
      7     public boolean onTouchEvent(MotionEvent event) {
      8         final int viewFlags = mViewFlags;
      9 
     10         if ((viewFlags & ENABLED_MASK) == DISABLED) {
     11             // A disabled view that is clickable still consumes the touch
     12             // events, it just doesn't respond to them.
     13             return (((viewFlags & CLICKABLE) == CLICKABLE ||
     14                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
     15         }
     16 
     17         if (mTouchDelegate != null) {
     18             if (mTouchDelegate.onTouchEvent(event)) {
     19                 return true;
     20             }
     21         }
     22 
     23         if (((viewFlags & CLICKABLE) == CLICKABLE ||
     24                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
     25             switch (event.getAction()) {
     26                 case MotionEvent.ACTION_UP:
     27                     boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
     28                     if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
     29                         // take focus if we don't have it already and we should in
     30                         // touch mode.
     31                         boolean focusTaken = false;
     32                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
     33                             focusTaken = requestFocus();
     34                         }
     35 
     36                         if (!mHasPerformedLongPress) {
     37                             // This is a tap, so remove the longpress check
     38                             removeLongPressCallback();
     39 
     40                             // Only perform take click actions if we were in the pressed state
     41                             if (!focusTaken) {
     42                                 // Use a Runnable and post this rather than calling
     43                                 // performClick directly. This lets other visual state
     44                                 // of the view update before click actions start.
     45                                 if (mPerformClick == null) {
     46                                     mPerformClick = new PerformClick();
     47                                 }
     48                                 if (!post(mPerformClick)) {
     49                                     performClick();
     50                                 }
     51                             }
     52                         }
     53 
     54                         if (mUnsetPressedState == null) {
     55                             mUnsetPressedState = new UnsetPressedState();
     56                         }
     57 
     58                         if (prepressed) {
     59                             mPrivateFlags |= PRESSED;
     60                             refreshDrawableState();
     61                             postDelayed(mUnsetPressedState,
     62                                     ViewConfiguration.getPressedStateDuration());
     63                         } else if (!post(mUnsetPressedState)) {
     64                             // If the post failed, unpress right now
     65                             mUnsetPressedState.run();
     66                         }
     67                         removeTapCallback();
     68                     }
     69                     break;
     70 
     71                 case MotionEvent.ACTION_DOWN:
     72                     if (mPendingCheckForTap == null) {
     73                         mPendingCheckForTap = new CheckForTap();
     74                     }
     75                     mPrivateFlags |= PREPRESSED;
     76                     mHasPerformedLongPress = false;
     77                     postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
     78                     break;
     79 
     80                 case MotionEvent.ACTION_CANCEL:
     81                     mPrivateFlags &= ~PRESSED;
     82                     refreshDrawableState();
     83                     removeTapCallback();
     84                     break;
     85 
     86                 case MotionEvent.ACTION_MOVE:
     87                     final int x = (int) event.getX();
     88                     final int y = (int) event.getY();
     89 
     90                     // Be lenient about moving outside of buttons
     91                     int slop = mTouchSlop;
     92                     if ((x < 0 - slop) || (x >= getWidth() + slop) ||
     93                             (y < 0 - slop) || (y >= getHeight() + slop)) {
     94                         // Outside button
     95                         removeTapCallback();
     96                         if ((mPrivateFlags & PRESSED) != 0) {
     97                             // Remove any future long press/tap checks
     98                             removeLongPressCallback();
     99 
    100                             // Need to switch from pressed to not pressed
    101                             mPrivateFlags &= ~PRESSED;
    102                             refreshDrawableState();
    103                         }
    104                     }
    105                     break;
    106             }
    107             return true;
    108         }
    109 
    110         return false;
    111     }
    View Code

    ViewGroup.java

      1     /**
      2      * {@inheritDoc}
      3      */
      4     @Override
      5     public boolean dispatchTouchEvent(MotionEvent ev) {
      6         if (!onFilterTouchEventForSecurity(ev)) {
      7             return false;
      8         }
      9 
     10         final int action = ev.getAction();
     11         final float xf = ev.getX();
     12         final float yf = ev.getY();
     13         final float scrolledXFloat = xf + mScrollX;
     14         final float scrolledYFloat = yf + mScrollY;
     15         final Rect frame = mTempRect;
     16 
     17         boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
     18 
     19         if (action == MotionEvent.ACTION_DOWN) {
     20             if (mMotionTarget != null) {
     21                 // this is weird, we got a pen down, but we thought it was
     22                 // already down!
     23                 // XXX: We should probably send an ACTION_UP to the current
     24                 // target.
     25                 mMotionTarget = null;
     26             }
     27             // If we're disallowing intercept or if we're allowing and we didn't
     28             // intercept
     29             if (disallowIntercept || !onInterceptTouchEvent(ev)) {
     30                 // reset this event's action (just to protect ourselves)
     31                 ev.setAction(MotionEvent.ACTION_DOWN);
     32                 // We know we want to dispatch the event down, find a child
     33                 // who can handle it, start with the front-most child.
     34                 final int scrolledXInt = (int) scrolledXFloat;
     35                 final int scrolledYInt = (int) scrolledYFloat;
     36                 final View[] children = mChildren;
     37                 final int count = mChildrenCount;
     38 
     39                 for (int i = count - 1; i >= 0; i--) {
     40                     final View child = children[i];
     41                     if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
     42                             || child.getAnimation() != null) {
     43                         child.getHitRect(frame);
     44                         if (frame.contains(scrolledXInt, scrolledYInt)) {
     45                             // offset the event to the view's coordinate system
     46                             final float xc = scrolledXFloat - child.mLeft;
     47                             final float yc = scrolledYFloat - child.mTop;
     48                             ev.setLocation(xc, yc);
     49                             child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
     50                             if (child.dispatchTouchEvent(ev))  {
     51                                 // Event handled, we have a target now.
     52                                 mMotionTarget = child;
     53                                 return true;
     54                             }
     55                             // The event didn't get handled, try the next view.
     56                             // Don't reset the event's location, it's not
     57                             // necessary here.
     58                         }
     59                     }
     60                 }
     61             }
     62         }
     63 
     64         boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
     65                 (action == MotionEvent.ACTION_CANCEL);
     66 
     67         if (isUpOrCancel) {
     68             // Note, we've already copied the previous state to our local
     69             // variable, so this takes effect on the next event
     70             mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
     71         }
     72 
     73         // The event wasn't an ACTION_DOWN, dispatch it to our target if
     74         // we have one.
     75         final View target = mMotionTarget;
     76         if (target == null) {
     77             // We don't have a target, this means we're handling the
     78             // event as a regular view.
     79             ev.setLocation(xf, yf);
     80             if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
     81                 ev.setAction(MotionEvent.ACTION_CANCEL);
     82                 mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
     83             }
     84             return super.dispatchTouchEvent(ev);
     85         }
     86 
     87         // if have a target, see if we're allowed to and want to intercept its
     88         // events
     89         if (!disallowIntercept && onInterceptTouchEvent(ev)) {
     90             final float xc = scrolledXFloat - (float) target.mLeft;
     91             final float yc = scrolledYFloat - (float) target.mTop;
     92             mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
     93             ev.setAction(MotionEvent.ACTION_CANCEL);
     94             ev.setLocation(xc, yc);
     95             if (!target.dispatchTouchEvent(ev)) {
     96                 // target didn't handle ACTION_CANCEL. not much we can do
     97                 // but they should have.
     98             }
     99             // clear the target
    100             mMotionTarget = null;
    101             // Don't dispatch this event to our own view, because we already
    102             // saw it when intercepting; we just want to give the following
    103             // event to the normal onTouchEvent().
    104             return true;
    105         }
    106 
    107         if (isUpOrCancel) {
    108             mMotionTarget = null;
    109         }
    110 
    111         // finally offset the event to the target's coordinate system and
    112         // dispatch the event.
    113         final float xc = scrolledXFloat - (float) target.mLeft;
    114         final float yc = scrolledYFloat - (float) target.mTop;
    115         ev.setLocation(xc, yc);
    116 
    117         if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
    118             ev.setAction(MotionEvent.ACTION_CANCEL);
    119             target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
    120             mMotionTarget = null;
    121         }
    122 
    123         return target.dispatchTouchEvent(ev);
    124     }
    View Code
  • 相关阅读:
    [帮助文档] [SageMath Thematic Tutorial] Chapter 10 使用Sagemath进行数值计算
    [转]dd命令、cp命令详解+dd命令、cp命令对比 delong
    MBR内容解析
    记一个编译错误:命名冲突、宏定义、头文件包含顺序
    防止STL容器迭代器失效
    日历时间
    观点
    编码规范
    《转》impress.js页面PPT
    <转>Spring Test 整合 JUnit 4 使用总结
  • 原文地址:https://www.cnblogs.com/wlrhnh/p/9117869.html
Copyright © 2020-2023  润新知