Java tutorial
/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.react.uimanager.events; import android.view.MotionEvent; import androidx.annotation.Nullable; import androidx.core.util.Pools; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.SoftAssertions; /** * An event representing the start, end or movement of a touch. Corresponds to a single {@link * android.view.MotionEvent}. * * <p>TouchEvent coalescing can happen for move events if two move events have the same target view * and coalescing key. See {@link TouchEventCoalescingKeyHelper} for more information about how * these coalescing keys are determined. */ public class TouchEvent extends Event<TouchEvent> { private static final int TOUCH_EVENTS_POOL_SIZE = 3; private static final Pools.SynchronizedPool<TouchEvent> EVENTS_POOL = new Pools.SynchronizedPool<>( TOUCH_EVENTS_POOL_SIZE); public static final long UNSET = Long.MIN_VALUE; public static TouchEvent obtain(int viewTag, TouchEventType touchEventType, MotionEvent motionEventToCopy, long gestureStartTime, float viewX, float viewY, TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { TouchEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new TouchEvent(); } event.init(viewTag, touchEventType, motionEventToCopy, gestureStartTime, viewX, viewY, touchEventCoalescingKeyHelper); return event; } private @Nullable MotionEvent mMotionEvent; private @Nullable TouchEventType mTouchEventType; private short mCoalescingKey; // Coordinates in the ViewTag coordinate space private float mViewX; private float mViewY; private TouchEvent() { } private void init(int viewTag, TouchEventType touchEventType, MotionEvent motionEventToCopy, long gestureStartTime, float viewX, float viewY, TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { super.init(viewTag); SoftAssertions.assertCondition(gestureStartTime != UNSET, "Gesture start time must be initialized"); short coalescingKey = 0; int action = (motionEventToCopy.getAction() & MotionEvent.ACTION_MASK); switch (action) { case MotionEvent.ACTION_DOWN: touchEventCoalescingKeyHelper.addCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_UP: touchEventCoalescingKeyHelper.removeCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_UP: touchEventCoalescingKeyHelper.incrementCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_MOVE: coalescingKey = touchEventCoalescingKeyHelper.getCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_CANCEL: touchEventCoalescingKeyHelper.removeCoalescingKey(gestureStartTime); break; default: throw new RuntimeException("Unhandled MotionEvent action: " + action); } mTouchEventType = touchEventType; mMotionEvent = MotionEvent.obtain(motionEventToCopy); mCoalescingKey = coalescingKey; mViewX = viewX; mViewY = viewY; } @Override public void onDispose() { Assertions.assertNotNull(mMotionEvent).recycle(); mMotionEvent = null; EVENTS_POOL.release(this); } @Override public String getEventName() { return TouchEventType.getJSEventName(Assertions.assertNotNull(mTouchEventType)); } @Override public boolean canCoalesce() { // We can coalesce move events but not start/end events. Coalescing move events should probably // append historical move data like MotionEvent batching does. This is left as an exercise for // the reader. switch (Assertions.assertNotNull(mTouchEventType)) { case START: case END: case CANCEL: return false; case MOVE: return true; default: throw new RuntimeException("Unknown touch event type: " + mTouchEventType); } } @Override public short getCoalescingKey() { return mCoalescingKey; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) { TouchesHelper.sendTouchEvent(rctEventEmitter, Assertions.assertNotNull(mTouchEventType), getViewTag(), this); } public MotionEvent getMotionEvent() { Assertions.assertNotNull(mMotionEvent); return mMotionEvent; } public float getViewX() { return mViewX; } public float getViewY() { return mViewY; } }