Permalink
Browse files

Fix NavigationCardStackPanResponder to work with native animations

Summary:
`NavigationCardStackPanResponder` uses `__getValue` and the `stopAnimation` callback value which both doesn't work with native driven animation. The workaround here is to add a value listener so the JS value of the AnimatedValue gets updated too so `__getValue` has a relatively up to date value. This value should be good unless JS lags behind native a lot but that should not happen during a navigation gesture. Also added a comment that explains the hack.

**Test plan**
Tested in an app that uses native driven animations with a back gesture. This also needs #10643 and #10641 for everything to work properly.
Closes #10642

Differential Revision: D4135496

Pulled By: ericvicenti

fbshipit-source-id: 395aff78b16a37ad9407207a05504fdd6311f733
  • Loading branch information...
1 parent 97d90a1 commit ac1927653463e766e270c87bb46833af67ee1fdc @janicduplessis janicduplessis committed with Facebook Github Bot Nov 5, 2016
@@ -22,6 +22,8 @@ import type {
NavigationSceneRendererProps,
} from 'NavigationTypeDefinition';
+const emptyFunction = () => {};
+
/**
* The duration of the card animation in milliseconds.
*/
@@ -92,6 +94,17 @@ class NavigationCardStackPanResponder extends NavigationAbstractPanResponder {
this._isVertical = direction === Directions.VERTICAL;
this._props = props;
this._startValue = 0;
+
+ // Hack to make this work with native driven animations. We add a single listener
+ // so the JS value of the following animated values gets updated. We rely on
+ // some Animated private APIs and not doing so would require using a bunch of
+ // value listeners but we'd have to remove them to not leak and I'm not sure
+ // when we'd do that with the current structure we have. `stopAnimation` callback
+ // is also broken with native animated values that have no listeners so if we
+ // want to remove this we have to fix this too.
+ this._addNativeListener(this._props.layout.width);
+ this._addNativeListener(this._props.layout.height);
+ this._addNativeListener(this._props.position);
}
onMoveShouldSetPanResponder(event: any, gesture: any): boolean {
@@ -210,6 +223,16 @@ class NavigationCardStackPanResponder extends NavigationAbstractPanResponder {
}
).start();
}
+
+ _addNativeListener(animatedValue) {
+ if (!animatedValue.__isNative) {
+ return;
+ }
+
+ if (Object.keys(animatedValue._listeners).length === 0) {
+ animatedValue.addListener(emptyFunction);
+ }
+ }
}
function createPanHandlers(

0 comments on commit ac19276

Please sign in to comment.