您的位置:首页 > 其它

View和ViewGroup的事件分发总结

2016-04-21 17:30 411 查看
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;
}


注意:一般情况下,onTouchEvent()都是返回true的,也是就当onTouchEvent()被调用的时候dispatchTouchEvent()的返回值一样,当onTouchEvent()返回true,剩下的action才能得以执行.

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的事件,自己进行处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: