mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Refactor EventDriverAnimations to customize event match
Summary: Changelog: [Internal] - Refactor match logic on determining whether to run an EventAnimationDriver (drivers for natively animated events) for an Event dispatched. Previously, drivers were stored by key on the NativeAnimatedNodesManager (based on event handler and viewTag) and has been refactored to be stored in a list for easier matching. This diff changes it so the match logic for running an EventAnimationDriver happens on the Event instance. This change is motivated by PointerEvents needing custom match logic (done on a following change). Reviewed By: javache Differential Revision: D40691002 fbshipit-source-id: e4f6742a2af3b751214aefa1fc069f65e8e71d77
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c565a770eb
commit
565a7439ac
@@ -21,8 +21,13 @@ import java.util.List;
|
||||
/* package */ class EventAnimationDriver implements RCTEventEmitter {
|
||||
private List<String> mEventPath;
|
||||
/* package */ ValueAnimatedNode mValueNode;
|
||||
/* package */ String mEventName;
|
||||
/* package */ int mViewTag;
|
||||
|
||||
public EventAnimationDriver(List<String> eventPath, ValueAnimatedNode valueNode) {
|
||||
public EventAnimationDriver(
|
||||
String eventName, int viewTag, List<String> eventPath, ValueAnimatedNode valueNode) {
|
||||
mEventName = eventName;
|
||||
mViewTag = viewTag;
|
||||
mEventPath = eventPath;
|
||||
mValueNode = valueNode;
|
||||
}
|
||||
|
||||
+43
-38
@@ -31,11 +31,9 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.EventDispatcherListener;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
@@ -58,9 +56,9 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
private final SparseArray<AnimatedNode> mAnimatedNodes = new SparseArray<>();
|
||||
private final SparseArray<AnimationDriver> mActiveAnimations = new SparseArray<>();
|
||||
private final SparseArray<AnimatedNode> mUpdatedNodes = new SparseArray<>();
|
||||
// Mapping of a view tag and an event name to a list of event animation drivers. 99% of the time
|
||||
// there will be only one driver per mapping so all code code should be optimized around that.
|
||||
private final Map<String, List<EventAnimationDriver>> mEventDrivers = new HashMap<>();
|
||||
// List of event animation drivers for an event on view.
|
||||
// There may be multiple drivers for the same event and view.
|
||||
private final List<EventAnimationDriver> mEventDrivers = new ArrayList<>();
|
||||
private final ReactApplicationContext mReactApplicationContext;
|
||||
private int mAnimatedGraphBFSColor = 0;
|
||||
// Used to avoid allocating a new array on every frame in `runUpdates` and `onEventDispatch`.
|
||||
@@ -501,7 +499,8 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void addAnimatedEventToView(int viewTag, String eventName, ReadableMap eventMapping) {
|
||||
public void addAnimatedEventToView(
|
||||
int viewTag, String eventHandlerName, ReadableMap eventMapping) {
|
||||
int nodeTag = eventMapping.getInt("animatedValueTag");
|
||||
AnimatedNode node = mAnimatedNodes.get(nodeTag);
|
||||
if (node == null) {
|
||||
@@ -512,8 +511,8 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"addAnimatedEventToView: Animated node on view ["
|
||||
+ viewTag
|
||||
+ "] connected to event ("
|
||||
+ eventName
|
||||
+ "] connected to event handler ("
|
||||
+ eventHandlerName
|
||||
+ ") should be of type "
|
||||
+ ValueAnimatedNode.class.getName());
|
||||
}
|
||||
@@ -524,32 +523,27 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
pathList.add(path.getString(i));
|
||||
}
|
||||
|
||||
EventAnimationDriver event = new EventAnimationDriver(pathList, (ValueAnimatedNode) node);
|
||||
String key = viewTag + eventName;
|
||||
if (mEventDrivers.containsKey(key)) {
|
||||
mEventDrivers.get(key).add(event);
|
||||
} else {
|
||||
List<EventAnimationDriver> drivers = new ArrayList<>(1);
|
||||
drivers.add(event);
|
||||
mEventDrivers.put(key, drivers);
|
||||
}
|
||||
String eventName = normalizeEventName(eventHandlerName);
|
||||
|
||||
EventAnimationDriver eventDriver =
|
||||
new EventAnimationDriver(eventName, viewTag, pathList, (ValueAnimatedNode) node);
|
||||
mEventDrivers.add(eventDriver);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void removeAnimatedEventFromView(int viewTag, String eventName, int animatedValueTag) {
|
||||
String key = viewTag + eventName;
|
||||
if (mEventDrivers.containsKey(key)) {
|
||||
List<EventAnimationDriver> driversForKey = mEventDrivers.get(key);
|
||||
if (driversForKey.size() == 1) {
|
||||
mEventDrivers.remove(viewTag + eventName);
|
||||
} else {
|
||||
ListIterator<EventAnimationDriver> it = driversForKey.listIterator();
|
||||
while (it.hasNext()) {
|
||||
if (it.next().mValueNode.mTag == animatedValueTag) {
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void removeAnimatedEventFromView(
|
||||
int viewTag, String eventHandlerName, int animatedValueTag) {
|
||||
|
||||
String eventName = normalizeEventName(eventHandlerName);
|
||||
|
||||
ListIterator<EventAnimationDriver> it = mEventDrivers.listIterator();
|
||||
while (it.hasNext()) {
|
||||
EventAnimationDriver driver = it.next();
|
||||
if (eventName.equals(driver.mEventName)
|
||||
&& viewTag == driver.mViewTag
|
||||
&& animatedValueTag == driver.mValueNode.mTag) {
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -585,18 +579,19 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
if (uiManager == null) {
|
||||
return;
|
||||
}
|
||||
String eventName = uiManager.resolveCustomDirectEventName(event.getEventName());
|
||||
if (eventName == null) {
|
||||
eventName = "";
|
||||
}
|
||||
|
||||
List<EventAnimationDriver> driversForKey = mEventDrivers.get(event.getViewTag() + eventName);
|
||||
if (driversForKey != null) {
|
||||
for (EventAnimationDriver driver : driversForKey) {
|
||||
boolean foundAtLeastOneDriver = false;
|
||||
Event.EventAnimationDriverMatchSpec matchSpec = event.getEventAnimationDriverMatchSpec();
|
||||
for (EventAnimationDriver driver : mEventDrivers) {
|
||||
if (matchSpec.match(driver.mViewTag, driver.mEventName)) {
|
||||
foundAtLeastOneDriver = true;
|
||||
stopAnimationsForNode(driver.mValueNode);
|
||||
event.dispatch(driver);
|
||||
mRunUpdateNodeList.add(driver.mValueNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (foundAtLeastOneDriver) {
|
||||
updateNodes(mRunUpdateNodeList);
|
||||
mRunUpdateNodeList.clear();
|
||||
}
|
||||
@@ -824,4 +819,14 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
mWarnedAboutGraphTraversal = false;
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeEventName(String eventHandlerName) {
|
||||
// Fabric UIManager also makes this assumption
|
||||
String eventName = eventHandlerName;
|
||||
if (eventHandlerName.startsWith("on")) {
|
||||
eventName = "top" + eventHandlerName.substring(2);
|
||||
}
|
||||
|
||||
return eventName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public abstract class Event<T extends Event> {
|
||||
private int mViewTag;
|
||||
private long mTimestampMs;
|
||||
private int mUniqueID = sUniqueID++;
|
||||
private @Nullable EventAnimationDriverMatchSpec mEventAnimationDriverMatchSpec;
|
||||
|
||||
protected Event() {}
|
||||
|
||||
@@ -165,6 +166,19 @@ public abstract class Event<T extends Event> {
|
||||
/** @return the name of this event as registered in JS */
|
||||
public abstract String getEventName();
|
||||
|
||||
public EventAnimationDriverMatchSpec getEventAnimationDriverMatchSpec() {
|
||||
if (mEventAnimationDriverMatchSpec == null) {
|
||||
mEventAnimationDriverMatchSpec =
|
||||
new EventAnimationDriverMatchSpec() {
|
||||
@Override
|
||||
public boolean match(int viewTag, String eventName) {
|
||||
return viewTag == getViewTag() && eventName.equals(getEventName());
|
||||
};
|
||||
};
|
||||
}
|
||||
return mEventAnimationDriverMatchSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch this event to JS using the given event emitter. Compatible with old and new renderer.
|
||||
* Instead of using this or dispatchModern, it is recommended that you simply override
|
||||
@@ -225,4 +239,8 @@ public abstract class Event<T extends Event> {
|
||||
}
|
||||
dispatch(rctEventEmitter);
|
||||
}
|
||||
|
||||
public interface EventAnimationDriverMatchSpec {
|
||||
boolean match(int viewTag, String eventName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user