我们接着上次的自定义星星来作讲解
当 onTouchEvent 返回 super.onTouchEvent ( false ) 时
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d("ACTION_DOWN","ACTION_DOWN:"+event.getAction());
break;
case MotionEvent.ACTION_MOVE:
Log.d("ACTION_MOVE","ACTION_MOVE:"+event.getAction());
break;
case MotionEvent.ACTION_UP:
Log.d("ACTION_UP","ACTION_UP:"+event.getAction());
break;
}
return super.onTouchEvent(event);
}
第一次会执行 DOWN 事件,DOWN 事件返回 false 之后,之后的 MOVE 事件和 UP 事件并没有触发。
设置为 false 之后,MOVE 事件和 UP 事件没有被执行。我们可以猜测一下,是不是被拦截了 ?事实是确实被拦截了
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
...
public boolean dispatchTouchEvent(MotionEvent ev) {
...
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
}
...
}
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
...
if (child == null) {
handled = super.dispatchTouchEvent(event);
} else {
handled = child.dispatchTouchEvent(event);
}
...
}
...
}
因为触摸时候存在子 View 所以会调用 child.dispatchTouchEvent(event)。
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
...
public boolean dispatchTouchEvent(MotionEvent event) {
...
//这里的onTouchEvent会调用到我们自定义的view中的onTouchEvent中去
if (!result && onTouchEvent(event)) {
result = true;
}
...
return result;
}
...
public boolean onTouchEvent(MotionEvent event) {
....
}
}
因为触摸时候存在子 View 所以会调用 child.dispatchTouchEvent(event)
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
...
public boolean dispatchTouchEvent(MotionEvent event) {
...
if (!result && onTouchEvent(event)) {
result = true;
}
...
return result;
}
...
public boolean onTouchEvent(MotionEvent event) {
....
}
}
如果 onTouchEvent 返回 super.onTouchEvent ( false ),那么 dispatchTouchEvent 返回的就是 false,dispatchTransformedTouchEvent 返回的也是 false。
接着看 ViewGroup
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
...
public boolean dispatchTouchEvent(MotionEvent ev) {
...
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
addTouchTarget(child, idBitsToAssign);
}
...
}
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
...
if (child == null) {
handled = super.dispatchTouchEvent(event);
} else {
handled = child.dispatchTouchEvent(event);
}
...
}
private TouchTarget addTouchTarget(@NonNull View child, int pointerIdBits) {
final TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
target.next = mFirstTouchTarget;
mFirstTouchTarget = target;
return target;
}
...
}
dispatchTransformedTouchEvent 返回 false,那么 addTouchTarget 就不会被调用,mFirstTouchTarget 就为默认值 null。
当第二次执行 MOVE 事件后,dispatchTouchEvent 方法会被再次调用。
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
...
public boolean dispatchTouchEvent(MotionEvent ev) {
...
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
if (!canceled && !intercepted) {
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
addTouchTarget(child, idBitsToAssign);
}
}
...
}
...
}
intercepted 为 true 时,dispatchTransformedTouchEvent 就不会被执行,child.dispatchTouchEvent 不会被调用,View 的 onTouchEvent 就不会被执行。
所以想要 onTouchEvent 不断的执行,只有将返回值设置成 true。