ViewGroup的源码分析

1. 说明


上节课我们看了ViewGroup的事件分发,分别有dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent等3个方法,我们也分析了几种常见情况,那么我们这节课就来从源码的角度来对ViewGroup进行分析。

2. 分析

2.1 : dispatchTouchEvent()

boolean handled = false;
        if (onFilterTouchEventForSecurity(ev)) {
            final int action = ev.getAction();
            final int actionMasked = action & MotionEvent.ACTION_MASK;

            // Handle an initial down.
            if (actionMasked == MotionEvent.ACTION_DOWN) {
                // Throw away all previous state when starting a new touch gesture.
                // The framework may have dropped the up or cancel event for the previous gesture
                // due to an app switch, ANR, or some other state change.
                cancelAndClearTouchTargets(ev);
                resetTouchState();
            }
/**
     * Cancels and clears all touch targets.
     */
    private void cancelAndClearTouchTargets(MotionEvent event) {
        if (mFirstTouchTarget != null) {
            boolean syntheticEvent = false;
            if (event == null) {
                final long now = SystemClock.uptimeMillis();
                event = MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                syntheticEvent = true;
            }

            for (TouchTarget target = mFirstTouchTarget; target != null; target = target.next) {
                resetCancelNextUpFlag(target.child);
                dispatchTransformedTouchEvent(event, true, target.child, target.pointerIdBits);
            }
            clearTouchTargets();

            if (syntheticEvent) {
                event.recycle();
            }
        }
    }
/**
     * Clears all touch targets.
     */
    private void clearTouchTargets() {
        TouchTarget target = mFirstTouchTarget;
        if (target != null) {
            do {
                TouchTarget next = target.next;
                target.recycle();
                target = next;
            } while (target != null);
            mFirstTouchTarget = null;
        }
    }

以上代码只需要知道:
当手指按下时,是清除TouchTargets,也就是说会把 mFirstTouchTarget = null;

DOWN事件正常情况下会调用

intercepted = onInterceptTouchEvent(ev);

默认情况下onInterceptTouchEvent 返回false

if (!canceled && !intercepted) {
    默认情况下是true,if语句可以执行
    if (newTouchTarget == null && childrenCount != 0) {
        DOWN的时候可以执行
        for (int i = childrenCount - 1; i >= 0; i--) {
         //  反序for循环
          if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
            //   如果 子 View返回true,就会执行下边方法 ,下边方法主要是给 mFirstTarget=target ;赋值
             newTouchTarget = addTouchTarget(child, idBitsToAssign);
          }
        }
    }
}
// Canceling motions is a special case.  We don't need to perform any transformations
        // or filtering.  The important part is the action, not the contents.
        final int oldAction = event.getAction();
        if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
            event.setAction(MotionEvent.ACTION_CANCEL);
            if (child == null) {
                //  如果child == null ,会调用 自己的  super  View.dispatchTouchEvent(event);
                handled = super.dispatchTouchEvent(event);
            } else {
                //  如果child 不为null,会调用  子类的child.dispatchTouchEvent(event);
                handled = child.dispatchTouchEvent(event);
            }
            event.setAction(oldAction);
            return handled;
        }

4. 事件分发总结

事件分发无非就是3个方法:
dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent,分别是事件分发、事件拦截、事件触摸;

对于自定义View来说:

如果该自定义View返回false,而不是返回true,表示不需要消费事件,那么就只会进来一次,只会相应DOWM事件,如果你想响应MOVE、UP事件,就必须找个地方返回true;

对于自定义ViewGroup来说:

如果你想拦截 子View 的 Touch事件,复写 onInterceptTouchEvent返回true即可;
如果说onInterceptTouchEvent 返回的是 true,表示ViewGroup会拦截事件,然后自己处理,这个时候会执行 ViewGroup的 onTouchEvent方法;
如果 子View没有一个地方返回 true,也就是说 子View没有消费 Touch事件,也会调用该 ViewGroup的 onTouchEvent

你可能感兴趣的:(ViewGroup的源码分析)