View和ViewGroup的事件分发总结
来源:互联网 发布:郑雨盛 知乎 编辑:程序博客网 时间:2024/05/06 07:54
View事件分发:
当为一个Button设置OnClickListener事件后,单击该Button,首先会调用View的dispatchTouchEvent()方法进行事件分发,Button是View的子类,故调用View的该方法,
当mOnTouchListener!=null,并且该view为enable激活状态的时候,以及onTouch()方法返回true的时候才会调用onTouchEvent()方法。我们在为View设置OnTouchListener的时候默认为mOnTouchListener赋值,并且Button默认为enable状态,所以当onTouch()返回false的时候,dispatchTouchEvent()方法直接返回true,不再响应事件.
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); }
如果为该Button也设置了OnClickListener,首先会执行onTouch()方法再执行onClick()方法,从上面可以得出onClick()方法与onTouchEvent(event)方法有关.
当event.getAction()==ACTION_UP时,会首先判断是否是OnLongClickListener(500ms后),否则执行performClick(),也就是onClick().
如果我们也设置了OnLongClickListener,那么会先执行onLongClick()方法,当返回值为false时(默认false),会继续执行onClick方法,否则不再继续执行.
public boolean onTouchEvent(MotionEvent event) { final int viewFlags = mViewFlags; if ((viewFlags & ENABLED_MASK) == DISABLED) { 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) { if (!mHasPerformedLongPress) { removeLongPressCallback(); if (!focusTaken) { if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClick(); } } } } 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: break; } return true; } return false; }
ViewGroup事件分发:
其实Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。,当一个ViewGroup中的一个子View发出onTouch事件的时候,首先由父类的dispatchTouchEvent()进行事件分发,再调用onInterceptTouchEvent方法对事件进行拦截(默认返回false),返回true则对事件进行拦截,不再对子View进行事件分发.
如果子View消费掉事件后,ViewGroup中将接收不到任何事件。
public boolean onInterceptTouchEvent(MotionEvent ev) { return false; }
public boolean dispatchTouchEvent(MotionEvent ev) { final int action = ev.getAction(); final float xf = ev.getX(); final float yf = ev.getY(); final float scrolledXFloat = xf + mScrollX; final float scrolledYFloat = yf + mScrollY; final Rect frame = mTempRect; boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; if (action == MotionEvent.ACTION_DOWN) { if (mMotionTarget != null) { mMotionTarget = null; } if (disallowIntercept || !onInterceptTouchEvent(ev)) { ev.setAction(MotionEvent.ACTION_DOWN); final int scrolledXInt = (int) scrolledXFloat; final int scrolledYInt = (int) scrolledYFloat; final View[] children = mChildren; final int count = mChildrenCount; for (int i = count - 1; i >= 0; i--) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { child.getHitRect(frame); if (frame.contains(scrolledXInt, scrolledYInt)) { final float xc = scrolledXFloat - child.mLeft; final float yc = scrolledYFloat - child.mTop; ev.setLocation(xc, yc); child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT; if (child.dispatchTouchEvent(ev)) { mMotionTarget = child; return true; } } } } } }
disallowIntercept 这个参数指是否禁用掉拦截功能,默认为false,子view可以通过调用getParent().requestDisallowInterceptTouchEvent(true)阻止ViewGroup对其MOVE或者UP事件进行拦截;同样ViewGroup也可以通过该属性返回true,拦截子View的事件,自己进行处理。
- View和ViewGroup的事件分发总结
- ViewGroup和View的事件分发机制
- View和ViewGroup的事件分发笔记
- View和ViewGroup事件分发
- Android View 与 ViewGroup 事件分发总结
- View和ViewGroup的事件分发机制详解
- Android之View和ViewGroup事件分发
- View和ViewGroup事件分发理解
- Android View 和 ViewGroup 事件分发机制
- android 事件分发 view和viewgroup
- ViewGroup与View的事件分发机制
- android之View和ViewGroup事件分发机制分析(一)(View的事件分发机制)
- Android View,ViewGroup 事件分发
- View & ViewGroup 之 事件分发
- Android View框架总结(八)ViewGroup事件分发机制
- Android View框架总结(八)ViewGroup事件分发机制
- ViewGroup的事件分发
- ViewGroup的事件分发
- 《CLR via C#:框架设计》读书笔记 - 接口
- "Content-Type" content="text/html; charset=utf-8"中content="text/html是啥意思呢?
- HTTP 头部字段
- 在递归调用时候可能return无法主动跳出使用主动抛出异常
- 三位数乘一位数
- View和ViewGroup的事件分发总结
- 马氏距离与欧式距离
- 解决The content of the adapter has changed but ListView did not receive a notification
- iOS 自动布局 Autolayout 报错:Unable to simultaneously satisfy constraints.
- 堆排序
- 关于论坛数据库的设计
- 鸽巢原理
- 仿Uber的侧拉视图
- 两位数乘一位数