onTouchEvent浅析

我们接着上次的自定义星星来作讲解
当 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。
onTouchEvent浅析_第1张图片

你可能感兴趣的:(java,算法,开发语言,android)