react-native-reanimated 3.0.0-rc.4 → 3.0.0-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.cpp +97 -15
- package/Common/cpp/LayoutAnimations/LayoutAnimationsProxy.h +32 -8
- package/Common/cpp/NativeModules/NativeReanimatedModule.cpp +16 -1
- package/Common/cpp/NativeModules/NativeReanimatedModule.h +8 -1
- package/Common/cpp/NativeModules/NativeReanimatedModuleSpec.cpp +17 -0
- package/Common/cpp/NativeModules/NativeReanimatedModuleSpec.h +8 -0
- package/Common/cpp/ReanimatedRuntime/ReanimatedRuntime.cpp +2 -1
- package/Common/cpp/ReanimatedRuntime/ReanimatedRuntime.h +1 -0
- package/Common/cpp/Tools/RuntimeDecorator.cpp +2 -1
- package/android/CMakeLists.txt +1 -0
- package/android/build.gradle +9 -1
- package/android/src/fabric/java/com/swmansion/reanimated/NativeProxy.java +16 -25
- package/android/src/main/cpp/LayoutAnimations.cpp +42 -50
- package/android/src/main/cpp/LayoutAnimations.h +17 -3
- package/android/src/main/cpp/NativeProxy.cpp +55 -6
- package/android/src/main/java/com/swmansion/reanimated/NodesManager.java +1 -1
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/AnimationsManager.java +208 -223
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/LayoutAnimations.java +7 -5
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/NativeMethodsHolder.java +5 -3
- package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ViewHierarchyObserver.java +1 -1
- package/android/src/paper/java/com/swmansion/reanimated/NativeProxy.java +20 -7
- package/android/src/reactNativeVersionPatch/nativeHierarchyManager/62/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java +8 -44
- package/android/src/reactNativeVersionPatch/nativeHierarchyManager/latest/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java +15 -61
- package/ios/LayoutReanimation/REAAnimationsManager.h +18 -8
- package/ios/LayoutReanimation/REAAnimationsManager.m +197 -162
- package/ios/LayoutReanimation/REAUIManager.mm +63 -70
- package/ios/native/NativeProxy.mm +55 -48
- package/lib/commonjs/createAnimatedComponent.js +26 -26
- package/lib/commonjs/createAnimatedComponent.js.map +1 -1
- package/lib/commonjs/reanimated2/NativeReanimated/NativeReanimated.js +4 -0
- package/lib/commonjs/reanimated2/NativeReanimated/NativeReanimated.js.map +1 -1
- package/lib/commonjs/reanimated2/core.js +9 -9
- package/lib/commonjs/reanimated2/core.js.map +1 -1
- package/lib/commonjs/reanimated2/globals.d.js.map +1 -1
- package/lib/commonjs/reanimated2/jestUtils.js +17 -9
- package/lib/commonjs/reanimated2/jestUtils.js.map +1 -1
- package/lib/commonjs/reanimated2/layoutReanimation/LayoutAnimationRepository.js +23 -62
- package/lib/commonjs/reanimated2/layoutReanimation/LayoutAnimationRepository.js.map +1 -1
- package/lib/module/createAnimatedComponent.js +27 -26
- package/lib/module/createAnimatedComponent.js.map +1 -1
- package/lib/module/reanimated2/NativeReanimated/NativeReanimated.js +4 -0
- package/lib/module/reanimated2/NativeReanimated/NativeReanimated.js.map +1 -1
- package/lib/module/reanimated2/core.js +7 -9
- package/lib/module/reanimated2/core.js.map +1 -1
- package/lib/module/reanimated2/globals.d.js.map +1 -1
- package/lib/module/reanimated2/jestUtils.js +17 -9
- package/lib/module/reanimated2/jestUtils.js.map +1 -1
- package/lib/module/reanimated2/layoutReanimation/LayoutAnimationRepository.js +22 -61
- package/lib/module/reanimated2/layoutReanimation/LayoutAnimationRepository.js.map +1 -1
- package/package.json +2 -2
- package/src/createAnimatedComponent.tsx +48 -39
- package/src/reanimated2/NativeReanimated/NativeReanimated.ts +15 -0
- package/src/reanimated2/core.ts +19 -10
- package/src/reanimated2/globals.d.ts +10 -6
- package/src/reanimated2/jestUtils.ts +14 -6
- package/src/reanimated2/layoutReanimation/LayoutAnimationRepository.ts +24 -50
- package/lib/commonjs/reanimated2/layoutReanimation/defaultAnimations/Default.js +0 -55
- package/lib/commonjs/reanimated2/layoutReanimation/defaultAnimations/Default.js.map +0 -1
- package/lib/module/reanimated2/layoutReanimation/defaultAnimations/Default.js +0 -40
- package/lib/module/reanimated2/layoutReanimation/defaultAnimations/Default.js.map +0 -1
- package/src/reanimated2/layoutReanimation/defaultAnimations/Default.ts +0 -49
|
@@ -203,7 +203,7 @@ void NativeProxy::installJSIBindings(
|
|
|
203
203
|
|
|
204
204
|
auto jsQueue = std::make_shared<JMessageQueueThread>(messageQueueThread);
|
|
205
205
|
std::shared_ptr<jsi::Runtime> animatedRuntime =
|
|
206
|
-
ReanimatedRuntime::make(jsQueue);
|
|
206
|
+
ReanimatedRuntime::make(runtime_, jsQueue);
|
|
207
207
|
|
|
208
208
|
auto workletRuntimeValue =
|
|
209
209
|
runtime_->global()
|
|
@@ -230,19 +230,68 @@ void NativeProxy::installJSIBindings(
|
|
|
230
230
|
|
|
231
231
|
// Layout Animations Start
|
|
232
232
|
|
|
233
|
-
auto
|
|
234
|
-
this->layoutAnimations->cthis()->
|
|
233
|
+
auto progressLayoutAnimation = [this](int tag, jsi::Value progress) {
|
|
234
|
+
this->layoutAnimations->cthis()->progressLayoutAnimation(tag, progress);
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
-
auto
|
|
238
|
-
this->layoutAnimations->cthis()->
|
|
237
|
+
auto endLayoutAnimation = [this](int tag, bool isCancelled, bool removeView) {
|
|
238
|
+
this->layoutAnimations->cthis()->endLayoutAnimation(
|
|
239
|
+
tag, isCancelled, removeView);
|
|
239
240
|
};
|
|
240
241
|
|
|
241
242
|
std::shared_ptr<LayoutAnimationsProxy> layoutAnimationsProxy =
|
|
242
243
|
std::make_shared<LayoutAnimationsProxy>(
|
|
243
|
-
|
|
244
|
+
progressLayoutAnimation, endLayoutAnimation, errorHandler);
|
|
244
245
|
std::weak_ptr<jsi::Runtime> wrt = animatedRuntime;
|
|
246
|
+
std::weak_ptr<LayoutAnimationsProxy> weakLayoutAnimationsProxy =
|
|
247
|
+
layoutAnimationsProxy;
|
|
245
248
|
layoutAnimations->cthis()->setWeakUIRuntime(wrt);
|
|
249
|
+
std::weak_ptr<ErrorHandler> weakErrorHandler = errorHandler;
|
|
250
|
+
|
|
251
|
+
layoutAnimations->cthis()->setAnimationStartingBlock(
|
|
252
|
+
[wrt, weakLayoutAnimationsProxy, weakErrorHandler](
|
|
253
|
+
int tag,
|
|
254
|
+
alias_ref<JString> type,
|
|
255
|
+
alias_ref<JMap<jstring, jstring>> values) {
|
|
256
|
+
auto runtime = wrt.lock();
|
|
257
|
+
auto layoutAnimationsProxy = weakLayoutAnimationsProxy.lock();
|
|
258
|
+
if (!runtime || !layoutAnimationsProxy) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
auto &rt = *runtime;
|
|
262
|
+
jsi::Object yogaValues(rt);
|
|
263
|
+
for (const auto &entry : *values) {
|
|
264
|
+
try {
|
|
265
|
+
auto key =
|
|
266
|
+
jsi::String::createFromAscii(rt, entry.first->toStdString());
|
|
267
|
+
auto value = stod(entry.second->toStdString());
|
|
268
|
+
yogaValues.setProperty(rt, key, value);
|
|
269
|
+
} catch (std::invalid_argument e) {
|
|
270
|
+
if (auto errorHandler = weakErrorHandler.lock()) {
|
|
271
|
+
errorHandler->setError("Failed to convert value to number");
|
|
272
|
+
errorHandler->raise();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
layoutAnimationsProxy->startLayoutAnimation(
|
|
278
|
+
*runtime, tag, type->toStdString(), yogaValues);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
layoutAnimations->cthis()->setHasAnimationBlock(
|
|
282
|
+
[weakLayoutAnimationsProxy](int tag, std::string type) {
|
|
283
|
+
auto layoutAnimationsProxy = weakLayoutAnimationsProxy.lock();
|
|
284
|
+
return layoutAnimationsProxy &&
|
|
285
|
+
layoutAnimationsProxy->hasLayoutAnimation(tag, type);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
layoutAnimations->cthis()->setClearAnimationConfigBlock(
|
|
289
|
+
[weakLayoutAnimationsProxy](int tag) {
|
|
290
|
+
auto layoutAnimationsProxy = weakLayoutAnimationsProxy.lock();
|
|
291
|
+
if (layoutAnimationsProxy) {
|
|
292
|
+
layoutAnimationsProxy->clearLayoutAnimationConfig(tag);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
246
295
|
|
|
247
296
|
// Layout Animations End
|
|
248
297
|
|
|
@@ -153,7 +153,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
153
153
|
// registration, creating race condition
|
|
154
154
|
mUIManager.getEventDispatcher().addListener(this);
|
|
155
155
|
|
|
156
|
-
mAnimationManager = new AnimationsManager(mContext,
|
|
156
|
+
mAnimationManager = new AnimationsManager(mContext, mUIManager);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
public void onHostPause() {
|
package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/AnimationsManager.java
CHANGED
|
@@ -16,9 +16,7 @@ import com.facebook.react.uimanager.IllegalViewOperationException;
|
|
|
16
16
|
import com.facebook.react.uimanager.PixelUtil;
|
|
17
17
|
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
|
18
18
|
import com.facebook.react.uimanager.RootView;
|
|
19
|
-
import com.facebook.react.uimanager.UIImplementation;
|
|
20
19
|
import com.facebook.react.uimanager.UIManagerModule;
|
|
21
|
-
import com.facebook.react.uimanager.ViewGroupManager;
|
|
22
20
|
import com.facebook.react.uimanager.ViewManager;
|
|
23
21
|
import com.swmansion.reanimated.Scheduler;
|
|
24
22
|
import java.lang.ref.WeakReference;
|
|
@@ -28,25 +26,17 @@ import java.util.HashSet;
|
|
|
28
26
|
import java.util.Map;
|
|
29
27
|
|
|
30
28
|
public class AnimationsManager implements ViewHierarchyObserver {
|
|
31
|
-
private static final String[] LAYOUT_KEYS = {
|
|
32
|
-
Snapshot.ORIGIN_X, Snapshot.ORIGIN_Y, Snapshot.WIDTH, Snapshot.HEIGHT
|
|
33
|
-
};
|
|
34
29
|
private WeakReference<Scheduler> mScheduler;
|
|
35
30
|
private ReactContext mContext;
|
|
36
|
-
private UIImplementation mUIImplementation;
|
|
37
31
|
private UIManagerModule mUIManager;
|
|
38
32
|
private NativeMethodsHolder mNativeMethodsHolder;
|
|
39
33
|
|
|
40
|
-
private HashMap<Integer,
|
|
41
|
-
private HashMap<Integer,
|
|
42
|
-
private HashSet<Integer>
|
|
43
|
-
private HashMap<Integer,
|
|
44
|
-
private HashMap<Integer, ViewManager> mParentViewManager;
|
|
45
|
-
private HashMap<Integer, View> mParent;
|
|
46
|
-
private HashMap<Integer, Runnable> mCallbacks;
|
|
47
|
-
private boolean mCleaningScheduled = false;
|
|
34
|
+
private HashMap<Integer, View> mExitingViews = new HashMap<>();
|
|
35
|
+
private HashMap<Integer, Integer> mExitingSubviewCountMap = new HashMap<>();
|
|
36
|
+
private HashSet<Integer> mAncestorsToRemove = new HashSet<>();
|
|
37
|
+
private HashMap<Integer, Runnable> mCallbacks = new HashMap<>();
|
|
48
38
|
private ReanimatedNativeHierarchyManager mReanimatedNativeHierarchyManager;
|
|
49
|
-
private boolean isCatalystInstanceDestroyed
|
|
39
|
+
private boolean isCatalystInstanceDestroyed;
|
|
50
40
|
|
|
51
41
|
public void setReanimatedNativeHierarchyManager(
|
|
52
42
|
ReanimatedNativeHierarchyManager reanimatedNativeHierarchyManager) {
|
|
@@ -61,26 +51,9 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
61
51
|
mScheduler = new WeakReference<>(scheduler);
|
|
62
52
|
}
|
|
63
53
|
|
|
64
|
-
public
|
|
65
|
-
Inactive,
|
|
66
|
-
Appearing,
|
|
67
|
-
Disappearing,
|
|
68
|
-
Layout,
|
|
69
|
-
ToRemove;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public AnimationsManager(
|
|
73
|
-
ReactContext context, UIImplementation uiImplementation, UIManagerModule uiManagerModule) {
|
|
54
|
+
public AnimationsManager(ReactContext context, UIManagerModule uiManagerModule) {
|
|
74
55
|
mContext = context;
|
|
75
|
-
mUIImplementation = uiImplementation;
|
|
76
56
|
mUIManager = uiManagerModule;
|
|
77
|
-
mStates = new HashMap<>();
|
|
78
|
-
mViewForTag = new HashMap<>();
|
|
79
|
-
mToRemove = new HashSet<>();
|
|
80
|
-
mViewManager = new HashMap<>();
|
|
81
|
-
mParentViewManager = new HashMap<>();
|
|
82
|
-
mParent = new HashMap();
|
|
83
|
-
mCallbacks = new HashMap<>();
|
|
84
57
|
isCatalystInstanceDestroyed = false;
|
|
85
58
|
}
|
|
86
59
|
|
|
@@ -88,41 +61,24 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
88
61
|
isCatalystInstanceDestroyed = true;
|
|
89
62
|
mNativeMethodsHolder = null;
|
|
90
63
|
mContext = null;
|
|
91
|
-
mUIImplementation = null;
|
|
92
64
|
mUIManager = null;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
mViewManager = null;
|
|
97
|
-
mParent = null;
|
|
98
|
-
mParentViewManager = null;
|
|
65
|
+
mExitingViews = null;
|
|
66
|
+
mExitingSubviewCountMap = null;
|
|
67
|
+
mAncestorsToRemove = null;
|
|
99
68
|
mCallbacks = null;
|
|
100
69
|
}
|
|
101
70
|
|
|
102
71
|
@Override
|
|
103
|
-
public void onViewRemoval(View view, ViewGroup parent,
|
|
72
|
+
public void onViewRemoval(View view, ViewGroup parent, Runnable callback) {
|
|
104
73
|
if (isCatalystInstanceDestroyed) {
|
|
105
74
|
return;
|
|
106
75
|
}
|
|
107
76
|
Integer tag = view.getId();
|
|
108
|
-
HashMap<String, Object> currentValues = before.toCurrentMap();
|
|
109
|
-
ViewState state = mStates.get(view.getId());
|
|
110
|
-
|
|
111
|
-
if (state == ViewState.Disappearing || state == ViewState.ToRemove) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
77
|
mCallbacks.put(tag, callback);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
mToRemove.add(view.getId());
|
|
119
|
-
scheduleCleaning();
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
78
|
+
|
|
79
|
+
if (!removeOrAnimateExitRecursive(view, parent, true)) {
|
|
80
|
+
removeView(view, parent);
|
|
122
81
|
}
|
|
123
|
-
mStates.put(tag, ViewState.Disappearing);
|
|
124
|
-
HashMap<String, Float> preparedValues = prepareDataForAnimationWorklet(currentValues, false);
|
|
125
|
-
mNativeMethodsHolder.startAnimationForTag(tag, "exiting", preparedValues);
|
|
126
82
|
}
|
|
127
83
|
|
|
128
84
|
@Override
|
|
@@ -130,27 +86,21 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
130
86
|
if (isCatalystInstanceDestroyed) {
|
|
131
87
|
return;
|
|
132
88
|
}
|
|
89
|
+
|
|
90
|
+
if (!hasAnimationForTag(view.getId(), "entering")) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
133
94
|
Scheduler strongScheduler = mScheduler.get();
|
|
134
95
|
if (strongScheduler != null) {
|
|
135
96
|
strongScheduler.triggerUI();
|
|
136
97
|
}
|
|
137
|
-
|
|
138
|
-
mStates.put(view.getId(), ViewState.Inactive);
|
|
139
|
-
mViewForTag.put(view.getId(), view);
|
|
140
|
-
mViewManager.put(view.getId(), after.viewManager);
|
|
141
|
-
mParentViewManager.put(view.getId(), after.parentViewManager);
|
|
142
|
-
mParent.put(view.getId(), after.parent);
|
|
143
|
-
}
|
|
144
|
-
Integer tag = view.getId();
|
|
98
|
+
int tag = view.getId();
|
|
145
99
|
HashMap<String, Object> targetValues = after.toTargetMap();
|
|
146
|
-
ViewState state = mStates.get(view.getId());
|
|
147
100
|
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
mNativeMethodsHolder.startAnimationForTag(tag, "entering", preparedValues);
|
|
152
|
-
}
|
|
153
|
-
return;
|
|
101
|
+
if (targetValues != null) {
|
|
102
|
+
HashMap<String, Float> preparedValues = prepareDataForAnimationWorklet(targetValues, true);
|
|
103
|
+
mNativeMethodsHolder.startAnimation(tag, "entering", preparedValues);
|
|
154
104
|
}
|
|
155
105
|
}
|
|
156
106
|
|
|
@@ -159,36 +109,32 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
159
109
|
if (isCatalystInstanceDestroyed) {
|
|
160
110
|
return;
|
|
161
111
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
ViewState state = mStates.get(view.getId());
|
|
166
|
-
if (state == null
|
|
167
|
-
|| state == ViewState.Disappearing
|
|
168
|
-
|| state == ViewState.ToRemove
|
|
169
|
-
|| state == ViewState.Inactive) {
|
|
112
|
+
int tag = view.getId();
|
|
113
|
+
|
|
114
|
+
if (!hasAnimationForTag(tag, "layout")) {
|
|
170
115
|
return;
|
|
171
116
|
}
|
|
117
|
+
|
|
118
|
+
HashMap<String, Object> targetValues = after.toTargetMap();
|
|
119
|
+
HashMap<String, Object> startValues = before.toCurrentMap();
|
|
120
|
+
|
|
172
121
|
// If startValues are equal to targetValues it means that there was no UI Operation changing
|
|
173
122
|
// layout of the View. So dirtiness of that View is false positive
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
doNotStartLayout = false;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (doNotStartLayout) {
|
|
186
|
-
return;
|
|
123
|
+
boolean doNotStartLayout = true;
|
|
124
|
+
for (int i = 0; i < Snapshot.targetKeysToTransform.size(); ++i) {
|
|
125
|
+
double startV =
|
|
126
|
+
((Number) startValues.get(Snapshot.currentKeysToTransform.get(i))).doubleValue();
|
|
127
|
+
double targetV =
|
|
128
|
+
((Number) targetValues.get(Snapshot.targetKeysToTransform.get(i))).doubleValue();
|
|
129
|
+
if (startV != targetV) {
|
|
130
|
+
doNotStartLayout = false;
|
|
187
131
|
}
|
|
188
132
|
}
|
|
133
|
+
if (doNotStartLayout) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
189
136
|
|
|
190
137
|
// View must be in Layout state
|
|
191
|
-
mStates.put(view.getId(), ViewState.Layout);
|
|
192
138
|
HashMap<String, Float> preparedStartValues = prepareDataForAnimationWorklet(startValues, false);
|
|
193
139
|
HashMap<String, Float> preparedTargetValues =
|
|
194
140
|
prepareDataForAnimationWorklet(targetValues, true);
|
|
@@ -196,60 +142,41 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
196
142
|
for (String key : preparedStartValues.keySet()) {
|
|
197
143
|
preparedValues.put(key, preparedStartValues.get(key));
|
|
198
144
|
}
|
|
199
|
-
mNativeMethodsHolder.
|
|
145
|
+
mNativeMethodsHolder.startAnimation(tag, "layout", preparedValues);
|
|
200
146
|
}
|
|
201
147
|
|
|
202
|
-
public void
|
|
203
|
-
|
|
204
|
-
if (state == ViewState.Inactive) {
|
|
205
|
-
mStates.put(tag, ViewState.Appearing);
|
|
206
|
-
}
|
|
148
|
+
public void progressLayoutAnimation(int tag, Map<String, Object> newStyle) {
|
|
149
|
+
View view = resolveView(tag);
|
|
207
150
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
mViewManager.get(tag),
|
|
212
|
-
mParentViewManager.get(tag),
|
|
213
|
-
mParent.get(tag).getId());
|
|
214
|
-
}
|
|
151
|
+
if (view == null) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
215
154
|
|
|
216
|
-
|
|
217
|
-
if (!cancelled) {
|
|
218
|
-
ViewState state = mStates.get(tag);
|
|
219
|
-
if (state == ViewState.Appearing) {
|
|
220
|
-
mStates.put(tag, ViewState.Layout);
|
|
221
|
-
}
|
|
155
|
+
ViewGroup parent = (ViewGroup) view.getParent();
|
|
222
156
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
mToRemove.add(tag);
|
|
226
|
-
scheduleCleaning();
|
|
227
|
-
}
|
|
157
|
+
if (parent == null) {
|
|
158
|
+
return;
|
|
228
159
|
}
|
|
160
|
+
|
|
161
|
+
ViewManager viewManager = resolveViewManager(tag);
|
|
162
|
+
ViewManager parentViewManager = resolveViewManager(parent.getId());
|
|
163
|
+
|
|
164
|
+
setNewProps(newStyle, view, viewManager, parentViewManager, parent.getId());
|
|
229
165
|
}
|
|
230
166
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
for (int tag : mToRemove) {
|
|
237
|
-
View view = mViewForTag.get(tag);
|
|
238
|
-
if (view == null) {
|
|
239
|
-
try {
|
|
240
|
-
view = mUIManager.resolveView(tag);
|
|
241
|
-
mViewForTag.put(tag, view);
|
|
242
|
-
} catch (IllegalViewOperationException ignored) {
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
findRoot(view, roots);
|
|
167
|
+
public void endLayoutAnimation(int tag, boolean cancelled, boolean removeView) {
|
|
168
|
+
View exitingView = mExitingViews.get(tag);
|
|
169
|
+
if (exitingView != null && removeView) {
|
|
170
|
+
if (exitingView instanceof ViewGroup && mAncestorsToRemove.contains(tag)) {
|
|
171
|
+
cancelAnimationsInSubviews((ViewGroup) exitingView);
|
|
247
172
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
173
|
+
|
|
174
|
+
mExitingViews.remove(tag);
|
|
175
|
+
maybeDropAncestors(exitingView);
|
|
176
|
+
|
|
177
|
+
ViewGroup parent = (ViewGroup) exitingView.getParent();
|
|
178
|
+
if (parent != null) {
|
|
179
|
+
removeView(exitingView, parent);
|
|
253
180
|
}
|
|
254
181
|
}
|
|
255
182
|
}
|
|
@@ -267,8 +194,6 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
267
194
|
}
|
|
268
195
|
out.append(" TAG:");
|
|
269
196
|
out.append(view.getId());
|
|
270
|
-
out.append(" STATE:");
|
|
271
|
-
out.append(this.mStates.get(view.getId()));
|
|
272
197
|
out.append(" CLASS:");
|
|
273
198
|
out.append(view.getClass().getSimpleName());
|
|
274
199
|
Log.v("rea", out.toString());
|
|
@@ -280,85 +205,6 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
280
205
|
}
|
|
281
206
|
}
|
|
282
207
|
|
|
283
|
-
private void scheduleCleaning() {
|
|
284
|
-
if (mCleaningScheduled) return;
|
|
285
|
-
mCleaningScheduled = true;
|
|
286
|
-
WeakReference<AnimationsManager> animationsManagerWeakReference = new WeakReference<>(this);
|
|
287
|
-
mContext.runOnUiQueueThread(
|
|
288
|
-
() -> {
|
|
289
|
-
mCleaningScheduled = false;
|
|
290
|
-
AnimationsManager thiz = animationsManagerWeakReference.get();
|
|
291
|
-
if (thiz == null) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
removeLeftovers();
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
private void findRoot(View view, HashSet<Integer> roots) {
|
|
299
|
-
View currentView = view;
|
|
300
|
-
int lastToRemoveTag = -1;
|
|
301
|
-
while (currentView != null) {
|
|
302
|
-
ViewState state = mStates.get(currentView.getId());
|
|
303
|
-
if (state == ViewState.Disappearing) {
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
if (state == ViewState.ToRemove) {
|
|
307
|
-
lastToRemoveTag = currentView.getId();
|
|
308
|
-
}
|
|
309
|
-
if (currentView.getParent() instanceof View) {
|
|
310
|
-
currentView = (View) currentView.getParent();
|
|
311
|
-
} else {
|
|
312
|
-
break;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
if (lastToRemoveTag != -1) {
|
|
316
|
-
roots.add(lastToRemoveTag);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
private boolean dfs(View root, View view, HashSet<Integer> cands) {
|
|
321
|
-
if ((!cands.contains(view.getId())) && (mStates.containsKey(view.getId()))) {
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
boolean cannotStripe = false;
|
|
325
|
-
if (view instanceof ViewGroup && mViewManager.get(view.getId()) instanceof ViewGroupManager) {
|
|
326
|
-
ViewGroup vg = (ViewGroup) view;
|
|
327
|
-
ViewGroupManager vgm = (ViewGroupManager) mViewManager.get(vg.getId());
|
|
328
|
-
ArrayList<View> children = new ArrayList<>();
|
|
329
|
-
for (int i = 0; i < vgm.getChildCount(vg); ++i) {
|
|
330
|
-
children.add(vgm.getChildAt(vg, i));
|
|
331
|
-
}
|
|
332
|
-
for (View child : children) {
|
|
333
|
-
cannotStripe = cannotStripe || dfs(root, child, cands);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (!cannotStripe) {
|
|
338
|
-
View parentView = (View) view.getParent();
|
|
339
|
-
if (mCallbacks.containsKey(view.getId())) {
|
|
340
|
-
Runnable runnable = mCallbacks.get(view.getId());
|
|
341
|
-
mCallbacks.remove(view.getId());
|
|
342
|
-
runnable.run();
|
|
343
|
-
}
|
|
344
|
-
if (mParent.containsKey(view.getId())) {
|
|
345
|
-
ViewGroup parent = (ViewGroup) mParent.get(view.getId());
|
|
346
|
-
if (parent != null) {
|
|
347
|
-
parent.removeView(view);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
View curView = view;
|
|
351
|
-
mStates.remove(curView.getId());
|
|
352
|
-
mViewForTag.remove(curView.getId());
|
|
353
|
-
mViewManager.remove(curView.getId());
|
|
354
|
-
mParentViewManager.remove(curView.getId());
|
|
355
|
-
mParent.remove(curView.getId());
|
|
356
|
-
mNativeMethodsHolder.removeConfigForTag(curView.getId());
|
|
357
|
-
mToRemove.remove(view.getId());
|
|
358
|
-
}
|
|
359
|
-
return cannotStripe;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
208
|
public HashMap<String, Float> prepareDataForAnimationWorklet(
|
|
363
209
|
HashMap<String, Object> values, boolean isTargetValues) {
|
|
364
210
|
HashMap<String, Float> preparedValues = new HashMap<>();
|
|
@@ -449,7 +295,7 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
449
295
|
} else if (value instanceof ReadableMap) {
|
|
450
296
|
propMap.putMap(key, (ReadableMap) value);
|
|
451
297
|
} else {
|
|
452
|
-
throw new IllegalStateException("Unknown type of animated value [Layout
|
|
298
|
+
throw new IllegalStateException("Unknown type of animated value [Layout Animations]");
|
|
453
299
|
}
|
|
454
300
|
}
|
|
455
301
|
|
|
@@ -512,8 +358,7 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
512
358
|
+ parentTag
|
|
513
359
|
+ " as a parent, but its Manager doesn't implement IViewManagerWithChildren");
|
|
514
360
|
}
|
|
515
|
-
if (parentViewManagerWithChildren
|
|
516
|
-
&& !parentViewManagerWithChildren.needsCustomLayoutForChildren()) {
|
|
361
|
+
if (!parentViewManagerWithChildren.needsCustomLayoutForChildren()) {
|
|
517
362
|
viewToUpdate.layout(x, y, x + width, y + height);
|
|
518
363
|
}
|
|
519
364
|
} else {
|
|
@@ -521,7 +366,147 @@ public class AnimationsManager implements ViewHierarchyObserver {
|
|
|
521
366
|
}
|
|
522
367
|
}
|
|
523
368
|
|
|
369
|
+
public boolean hasAnimationForTag(int tag, String type) {
|
|
370
|
+
return mNativeMethodsHolder.hasAnimation(tag, type);
|
|
371
|
+
}
|
|
372
|
+
|
|
524
373
|
public boolean isLayoutAnimationEnabled() {
|
|
525
374
|
return mNativeMethodsHolder != null && mNativeMethodsHolder.isLayoutAnimationEnabled();
|
|
526
375
|
}
|
|
376
|
+
|
|
377
|
+
private boolean removeOrAnimateExitRecursive(View view, ViewGroup parent, boolean shouldRemove) {
|
|
378
|
+
int tag = view.getId();
|
|
379
|
+
boolean hasExitAnimation = hasAnimationForTag(tag, "exiting") || mExitingViews.containsKey(tag);
|
|
380
|
+
boolean hasAnimatedChildren = false;
|
|
381
|
+
shouldRemove = shouldRemove && !hasExitAnimation;
|
|
382
|
+
|
|
383
|
+
ArrayList<View> toBeRemoved = new ArrayList<>();
|
|
384
|
+
|
|
385
|
+
// we might want to keep this view around
|
|
386
|
+
// because one of the (children's) children
|
|
387
|
+
// has an exiting animation
|
|
388
|
+
if (view instanceof ViewGroup) {
|
|
389
|
+
ViewGroup viewGroup = (ViewGroup) view;
|
|
390
|
+
for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) {
|
|
391
|
+
View child = viewGroup.getChildAt(i);
|
|
392
|
+
if (removeOrAnimateExitRecursive(child, viewGroup, shouldRemove)) {
|
|
393
|
+
hasAnimatedChildren = true;
|
|
394
|
+
} else if (shouldRemove) {
|
|
395
|
+
toBeRemoved.add(child);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
boolean wantAnimateExit = hasExitAnimation || hasAnimatedChildren;
|
|
401
|
+
|
|
402
|
+
if (hasExitAnimation) {
|
|
403
|
+
Snapshot before = new Snapshot(view, mReanimatedNativeHierarchyManager);
|
|
404
|
+
HashMap<String, Object> currentValues = before.toCurrentMap();
|
|
405
|
+
HashMap<String, Float> preparedValues = prepareDataForAnimationWorklet(currentValues, false);
|
|
406
|
+
if (!mExitingViews.containsKey(tag)) {
|
|
407
|
+
mExitingViews.put(tag, view);
|
|
408
|
+
registerExitingAncestors(view);
|
|
409
|
+
mNativeMethodsHolder.startAnimation(tag, "exiting", preparedValues);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
mNativeMethodsHolder.clearAnimationConfig(tag);
|
|
414
|
+
|
|
415
|
+
if (!wantAnimateExit) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (hasAnimatedChildren) {
|
|
420
|
+
mAncestorsToRemove.add(tag);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
for (View child : toBeRemoved) {
|
|
424
|
+
removeView(child, (ViewGroup) view);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private void registerExitingAncestors(View view) {
|
|
431
|
+
View parent = (View) view.getParent();
|
|
432
|
+
while (parent != null && !(parent instanceof RootView)) {
|
|
433
|
+
int tag = parent.getId();
|
|
434
|
+
Integer previousValue = mExitingSubviewCountMap.get(tag);
|
|
435
|
+
int newValue = previousValue != null ? previousValue + 1 : 1;
|
|
436
|
+
mExitingSubviewCountMap.put(tag, newValue);
|
|
437
|
+
|
|
438
|
+
parent = (View) parent.getParent();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private void maybeDropAncestors(View exitingView) {
|
|
443
|
+
View parent = (View) exitingView.getParent();
|
|
444
|
+
while (parent != null && !(parent instanceof RootView)) {
|
|
445
|
+
View view = parent;
|
|
446
|
+
parent = (View) view.getParent();
|
|
447
|
+
int tag = view.getId();
|
|
448
|
+
Integer ancestorOfCount = mExitingSubviewCountMap.get(tag);
|
|
449
|
+
ancestorOfCount = ancestorOfCount != null ? ancestorOfCount - 1 : 0;
|
|
450
|
+
if (ancestorOfCount <= 0) {
|
|
451
|
+
if (mAncestorsToRemove.contains(tag)) {
|
|
452
|
+
mAncestorsToRemove.remove(tag);
|
|
453
|
+
if (!mExitingViews.containsKey(tag)) {
|
|
454
|
+
removeView(view, (ViewGroup) parent);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
mExitingSubviewCountMap.remove(tag);
|
|
458
|
+
} else {
|
|
459
|
+
mExitingSubviewCountMap.put(tag, ancestorOfCount);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
private void removeView(View view, ViewGroup parent) {
|
|
465
|
+
int tag = view.getId();
|
|
466
|
+
if (mCallbacks.containsKey(tag)) {
|
|
467
|
+
Runnable callback = mCallbacks.get(tag);
|
|
468
|
+
mCallbacks.remove(tag);
|
|
469
|
+
if (callback != null) {
|
|
470
|
+
callback.run();
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
mReanimatedNativeHierarchyManager.publicDropView(view);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
parent.removeView(view);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
private void cancelAnimationsInSubviews(ViewGroup view) {
|
|
480
|
+
for (int i = view.getChildCount() - 1; i >= 0; i--) {
|
|
481
|
+
View child = view.getChildAt(i);
|
|
482
|
+
|
|
483
|
+
if (mExitingViews.containsKey(child.getId())) {
|
|
484
|
+
endLayoutAnimation(child.getId(), true, true);
|
|
485
|
+
} else if (child instanceof ViewGroup && mAncestorsToRemove.contains(child.getId())) {
|
|
486
|
+
cancelAnimationsInSubviews((ViewGroup) child);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
private View resolveView(int tag) {
|
|
492
|
+
if (mExitingViews.containsKey(tag)) {
|
|
493
|
+
return mExitingViews.get(tag);
|
|
494
|
+
}
|
|
495
|
+
try {
|
|
496
|
+
return mUIManager.resolveView(tag);
|
|
497
|
+
} catch (IllegalViewOperationException e) {
|
|
498
|
+
// view has been removed already
|
|
499
|
+
e.printStackTrace();
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
private ViewManager resolveViewManager(int tag) {
|
|
505
|
+
try {
|
|
506
|
+
return mReanimatedNativeHierarchyManager.resolveViewManager(tag);
|
|
507
|
+
} catch (Exception e) {
|
|
508
|
+
e.printStackTrace();
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
527
512
|
}
|
package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/LayoutAnimations.java
CHANGED
|
@@ -29,29 +29,31 @@ public class LayoutAnimations {
|
|
|
29
29
|
// LayoutReanimation
|
|
30
30
|
public native void startAnimationForTag(int tag, String type, Map<String, String> values);
|
|
31
31
|
|
|
32
|
-
public native
|
|
32
|
+
public native boolean hasAnimationForTag(int tag, String type);
|
|
33
|
+
|
|
34
|
+
public native void clearAnimationConfigForTag(int tag);
|
|
33
35
|
|
|
34
36
|
public native boolean isLayoutAnimationEnabled();
|
|
35
37
|
|
|
36
|
-
private void
|
|
38
|
+
private void endLayoutAnimation(int tag, boolean cancelled, boolean removeView) {
|
|
37
39
|
ReactApplicationContext context = mContext.get();
|
|
38
40
|
if (context != null) {
|
|
39
41
|
context
|
|
40
42
|
.getNativeModule(ReanimatedModule.class)
|
|
41
43
|
.getNodesManager()
|
|
42
44
|
.getAnimationsManager()
|
|
43
|
-
.
|
|
45
|
+
.endLayoutAnimation(tag, cancelled, removeView);
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
private void
|
|
49
|
+
private void progressLayoutAnimation(int tag, Map<String, Object> newStyle) {
|
|
48
50
|
ReactApplicationContext context = mContext.get();
|
|
49
51
|
if (context != null) {
|
|
50
52
|
context
|
|
51
53
|
.getNativeModule(ReanimatedModule.class)
|
|
52
54
|
.getNodesManager()
|
|
53
55
|
.getAnimationsManager()
|
|
54
|
-
.
|
|
56
|
+
.progressLayoutAnimation(tag, newStyle);
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
}
|