古人学问无遗力,少壮工夫老始成。这篇文章主要讲述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*/ 7public boolean onTouchEvent(MotionEvent event) { 8final int viewFlags = mViewFlags; 9 10if ((viewFlags & ENABLED_MASK) == DISABLED) { 11// A disabled view that is clickable still consumes the touch 12// events, it just doesn‘t respond to them. 13return (((viewFlags & CLICKABLE) == CLICKABLE || 14(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 15} 16 17if (mTouchDelegate != null) { 18if (mTouchDelegate.onTouchEvent(event)) { 19return true; 20} 21} 22 23if (((viewFlags & CLICKABLE) == CLICKABLE || 24(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 25switch (event.getAction()) { 26case MotionEvent.ACTION_UP: 27boolean prepressed = (mPrivateFlags & PREPRESSED) != 0; 28if ((mPrivateFlags & PRESSED) != 0 || prepressed) { 29// take focus if we don‘t have it already and we should in 30// touch mode. 31boolean focusTaken = false; 32if (isFocusable() & & isFocusableInTouchMode() & & !isFocused()) { 33focusTaken = requestFocus(); 34} 35 36if (!mHasPerformedLongPress) { 37// This is a tap, so remove the longpress check 38removeLongPressCallback(); 39 40// Only perform take click actions if we were in the pressed state 41if (!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. 45if (mPerformClick == null) { 46mPerformClick = new PerformClick(); 47} 48if (!post(mPerformClick)) { 49performClick(); 50} 51} 52} 53 54if (mUnsetPressedState == null) { 55mUnsetPressedState = new UnsetPressedState(); 56} 57 58if (prepressed) { 59mPrivateFlags |= PRESSED; 60refreshDrawableState(); 61postDelayed(mUnsetPressedState, 62ViewConfiguration.getPressedStateDuration()); 63} else if (!post(mUnsetPressedState)) { 64// If the post failed, unpress right now 65mUnsetPressedState.run(); 66} 67removeTapCallback(); 68} 69break; 70 71case MotionEvent.ACTION_DOWN: 72if (mPendingCheckForTap == null) { 73mPendingCheckForTap = new CheckForTap(); 74} 75mPrivateFlags |= PREPRESSED; 76mHasPerformedLongPress = false; 77postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 78break; 79 80case MotionEvent.ACTION_CANCEL: 81mPrivateFlags & = ~PRESSED; 82refreshDrawableState(); 83removeTapCallback(); 84break; 85 86case MotionEvent.ACTION_MOVE: 87final int x = (int) event.getX(); 88final int y = (int) event.getY(); 89 90// Be lenient about moving outside of buttons 91int slop = mTouchSlop; 92if ((x < 0 - slop) || (x > = getWidth() + slop) || 93(y < 0 - slop) || (y > = getHeight() + slop)) { 94// Outside button 95removeTapCallback(); 96if ((mPrivateFlags & PRESSED) != 0) { 97// Remove any future long press/tap checks 98removeLongPressCallback(); 99 100// Need to switch from pressed to not pressed 101mPrivateFlags & = ~PRESSED; 102refreshDrawableState(); 103} 104} 105break; 106} 107return true; 108} 109 110return false; 111}
View Code
ViewGroup.java
文章图片
文章图片
1/** 2* {@inheritDoc} 3*/ 4@Override 5public boolean dispatchTouchEvent(MotionEvent ev) { 6if (!onFilterTouchEventForSecurity(ev)) { 7return false; 8} 9 10final int action = ev.getAction(); 11final float xf = ev.getX(); 12final float yf = ev.getY(); 13final float scrolledXFloat = xf + mScrollX; 14final float scrolledYFloat = yf + mScrollY; 15final Rect frame = mTempRect; 16 17boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; 18 19if (action == MotionEvent.ACTION_DOWN) { 20if (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. 25mMotionTarget = null; 26} 27// If we‘re disallowing intercept or if we‘re allowing and we didn‘t 28// intercept 29if (disallowIntercept || !onInterceptTouchEvent(ev)) { 30// reset this event‘s action (just to protect ourselves) 31ev.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. 34final int scrolledXInt = (int) scrolledXFloat; 35final int scrolledYInt = (int) scrolledYFloat; 36final View[] children = mChildren; 37final int count = mChildrenCount; 38 39for (int i = count - 1; i > = 0; i--) { 40final View child = children[i]; 41if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE 42|| child.getAnimation() != null) { 43child.getHitRect(frame); 44if (frame.contains(scrolledXInt, scrolledYInt)) { 45// offset the event to the view‘s coordinate system 46final float xc = scrolledXFloat - child.mLeft; 47final float yc = scrolledYFloat - child.mTop; 48ev.setLocation(xc, yc); 49child.mPrivateFlags & = ~CANCEL_NEXT_UP_EVENT; 50if (child.dispatchTouchEvent(ev)){ 51// Event handled, we have a target now. 52mMotionTarget = child; 53return 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 64boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) || 65(action == MotionEvent.ACTION_CANCEL); 66 67if (isUpOrCancel) { 68// Note, we‘ve already copied the previous state to our local 69// variable, so this takes effect on the next event 70mGroupFlags & = ~FLAG_DISALLOW_INTERCEPT; 71} 72 73// The event wasn‘t an ACTION_DOWN, dispatch it to our target if 74// we have one. 75final View target = mMotionTarget; 76if (target == null) { 77// We don‘t have a target, this means we‘re handling the 78// event as a regular view. 79ev.setLocation(xf, yf); 80if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) { 81ev.setAction(MotionEvent.ACTION_CANCEL); 82mPrivateFlags & = ~CANCEL_NEXT_UP_EVENT; 83} 84return super.dispatchTouchEvent(ev); 85} 86 87// if have a target, see if we‘re allowed to and want to intercept its 88// events 89if (!disallowIntercept & & onInterceptTouchEvent(ev)) { 90final float xc = scrolledXFloat - (float) target.mLeft; 91final float yc = scrolledYFloat - (float) target.mTop; 92mPrivateFlags & = ~CANCEL_NEXT_UP_EVENT; 93ev.setAction(MotionEvent.ACTION_CANCEL); 94ev.setLocation(xc, yc); 95if (!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 100mMotionTarget = 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(). 104return true; 105} 106 107if (isUpOrCancel) { 108mMotionTarget = null; 109} 110 111// finally offset the event to the target‘s coordinate system and 112// dispatch the event. 113final float xc = scrolledXFloat - (float) target.mLeft; 114final float yc = scrolledYFloat - (float) target.mTop; 115ev.setLocation(xc, yc); 116 117if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) { 118ev.setAction(MotionEvent.ACTION_CANCEL); 119target.mPrivateFlags & = ~CANCEL_NEXT_UP_EVENT; 120mMotionTarget = null; 121} 122 123return target.dispatchTouchEvent(ev); 124}
View Code【Android Touch事件相关源码Android SourceCode 2.3.6】
推荐阅读
- AndroidGradle最实用的指南
- appium的inspectot使用
- tp3.2支付宝app支付
- springmvc配置中,mapper一直依赖注入不进去的问题记录
- apply bind call 和 this
- Android_(消息提示)多种使用Toast的消息提示
- Android安全编码
- 五步打造APP节日主题设计(以Lofter新年图标设计为例)
- 事件(Application Event)