Skip to content

Commit

Permalink
return final animation values to JS when animation completes (#36731)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #36731

When using the native driver for animations that involve layout changes (ie. translateY and other transforms, but not styles such as opacity), because it bypasses Fabric, the new coordinates are not updated so the Pressability responder region/tap target is incorrect

**This diff:**
- Returning the final values from the native side, at the same place it sets the "finished" flag. This gets sent to JS in `animated/animations/Animation.js`. In this diff I'm passing the value when 'hasFinishedAnimations' is true, but in a follow up diff I will look into other cases such as cancelled animations

Next:
2. Update the Animated.Value to reflect the new values
3. Call the onEnd function if there is one set
4. Use `setNativeProps` to pass the new values down for layout calculations and the correct Pressability responder region

Changelog:
[General][Changed] - return animated values to JS for natively driven animations

Differential Revision: D44110833

fbshipit-source-id: 3418aed9ae724d33dcedb0e678a7e5b4c89ca65e
  • Loading branch information
skinsshark authored and facebook-github-bot committed Mar 31, 2023
1 parent ed448b5 commit f81aa00
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ const parallel = function (
}

animations.forEach((animation, idx) => {
const cb = function (endResult: EndResult | {finished: boolean}) {
const cb = function (endResult: EndResult) {
hasEnded[idx] = true;
doneCount++;
if (doneCount === animations.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {TurboModule} from '../TurboModule/RCTExport';

import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';

type EndResult = {finished: boolean, ...};
type EndResult = {finished: boolean, value?: number, ...};
type EndCallback = (result: EndResult) => void;
type SaveValueCallback = (value: number) => void;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {TurboModule} from '../TurboModule/RCTExport';

import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';

type EndResult = {finished: boolean, ...};
type EndResult = {finished: boolean, value?: number, ...};
type EndCallback = (result: EndResult) => void;
type SaveValueCallback = (value: number) => void;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type AnimatedValue from '../nodes/AnimatedValue';

import NativeAnimatedHelper from '../NativeAnimatedHelper';

export type EndResult = {finished: boolean, ...};
export type EndResult = {finished: boolean, value?: number, ...};
export type EndCallback = (result: EndResult) => void;

export type AnimationConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,17 +640,16 @@ public void runUpdates(long frameTimeNanos) {
for (int i = mActiveAnimations.size() - 1; i >= 0; i--) {
AnimationDriver animation = mActiveAnimations.valueAt(i);
if (animation.mHasFinished) {
WritableMap params = Arguments.createMap();
params.putBoolean("finished", true);
params.putDouble("value", animation.mAnimatedValue.mValue);
if (animation.mEndCallback != null) {
WritableMap endCallbackResponse = Arguments.createMap();
endCallbackResponse.putBoolean("finished", true);
animation.mEndCallback.invoke(endCallbackResponse);
animation.mEndCallback.invoke(params);
} else if (mReactApplicationContext != null) {
// If no callback is passed in, this /may/ be an animation set up by the single-op
// instruction from JS, meaning that no jsi::functions are passed into native and
// we communicate via RCTDeviceEventEmitter instead of callbacks.
WritableMap params = Arguments.createMap();
params.putInt("animationId", animation.mId);
params.putBoolean("finished", true);
mReactApplicationContext.emitDeviceEvent(
"onNativeAnimatedModuleAnimationFinished", params);
}
Expand Down

0 comments on commit f81aa00

Please sign in to comment.