Add optional configs to constructors for AnimatedValue/ValueXY/Color

Summary:
There are use cases of needing to setValue multiple times per second (for example, using PanResponder to update a slider component).

This requires the use of the native driver for perf reasons as using the JS driver will cause a rerender. Currently, the only way to make an animated node native is via setting useNativeDriver: true on an animation config. For example:
```
Animated.timing(animatedValue,
{
  toValue: newValue,
  duration: 0,
  useNativeDriver: true
}).start();
```

To avoid needing to call the above, add a useNativeDriver param to the constructor. When set to true, the node will be made native immediately.

```
const animatedValue = new Animated.Value(0, useNativeDriver);
...
animatedValue.setValue(newValue);
```

Note that, like with useNativeDriver in the animation config, once a node is made native, it cannot be reverted to JS-only.

 ---

As an aside, PanResponder uses JS-side events, and thus we cannot use Animated.event with native driver; we instead need to setValue on a native AnimatedValue. A much more thorough explanation is in D34564598.

 ---

Changelog:
[General][Added] - [Animated] Add useNativeDriver as a param for setValue

Reviewed By: JoshuaGross

Differential Revision: D36459457

fbshipit-source-id: 284148a6d16537429efeab8b07184019990909cd
This commit is contained in:
Genki Kondo 2022-05-20 10:42:40 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 841793a281
Коммит 73191edb72
3 изменённых файлов: 45 добавлений и 8 удалений

Просмотреть файл

@ -21,6 +21,9 @@ import type {ColorValue} from '../../StyleSheet/StyleSheet';
import type {NativeColorValue} from '../../StyleSheet/PlatformColorValueTypes';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
export type AnimatedColorConfig = $ReadOnly<{
useNativeDriver: boolean,
}>;
type ColorListenerCallback = (value: string) => mixed;
export type RgbaValue = {
+r: number,
@ -116,7 +119,10 @@ export default class AnimatedColor extends AnimatedWithChildren {
...
} = {};
constructor(valueIn?: ?(RgbaValue | RgbaAnimatedValue | ColorValue)) {
constructor(
valueIn?: ?(RgbaValue | RgbaAnimatedValue | ColorValue),
config?: ?AnimatedColorConfig,
) {
super();
let value: RgbaValue | RgbaAnimatedValue | ColorValue =
valueIn ?? defaultColor;
@ -144,14 +150,11 @@ export default class AnimatedColor extends AnimatedWithChildren {
this.g = new AnimatedValue(initColor.g);
this.b = new AnimatedValue(initColor.b);
this.a = new AnimatedValue(initColor.a);
if (this.nativeColor) {
if (!this.__isNative) {
}
if (this.nativeColor || (config && config.useNativeDriver)) {
this.__makeNative();
}
}
}
}
/**
* Directly set the value. This will stop any animations running on the value

Просмотреть файл

@ -20,6 +20,10 @@ import type Animation, {EndCallback} from '../animations/Animation';
import type {InterpolationConfigType} from './AnimatedInterpolation';
import type AnimatedTracking from './AnimatedTracking';
export type AnimatedValueConfig = $ReadOnly<{
useNativeDriver: boolean,
}>;
const NativeAnimatedAPI = NativeAnimatedHelper.API;
/**
@ -87,7 +91,7 @@ class AnimatedValue extends AnimatedWithChildren {
_animation: ?Animation;
_tracking: ?AnimatedTracking;
constructor(value: number) {
constructor(value: number, config?: ?AnimatedValueConfig) {
super();
if (typeof value !== 'number') {
throw new Error('AnimatedValue: Attempting to set value to undefined');
@ -95,6 +99,9 @@ class AnimatedValue extends AnimatedWithChildren {
this._startingValue = this._value = value;
this._offset = 0;
this._animation = null;
if (config && config.useNativeDriver) {
this.__makeNative();
}
}
__detach() {

Просмотреть файл

@ -10,11 +10,16 @@
'use strict';
import type {PlatformConfig} from '../AnimatedPlatformConfig';
const AnimatedValue = require('./AnimatedValue');
const AnimatedWithChildren = require('./AnimatedWithChildren');
const invariant = require('invariant');
export type AnimatedValueXYConfig = $ReadOnly<{
useNativeDriver: boolean,
}>;
type ValueXYListenerCallback = (value: {
x: number,
y: number,
@ -47,6 +52,7 @@ class AnimatedValueXY extends AnimatedWithChildren {
+y: number | AnimatedValue,
...
},
config?: ?AnimatedValueXYConfig,
) {
super();
const value: any = valueIn || {x: 0, y: 0}; // @flowfixme: shouldn't need `: any`
@ -63,6 +69,9 @@ class AnimatedValueXY extends AnimatedWithChildren {
this.y = value.y;
}
this._listeners = {};
if (config && config.useNativeDriver) {
this.__makeNative();
}
}
/**
@ -221,6 +230,24 @@ class AnimatedValueXY extends AnimatedWithChildren {
getTranslateTransform(): Array<{[key: string]: AnimatedValue, ...}> {
return [{translateX: this.x}, {translateY: this.y}];
}
__attach(): void {
this.x.__addChild(this);
this.y.__addChild(this);
super.__attach();
}
__detach(): void {
this.x.__removeChild(this);
this.y.__removeChild(this);
super.__detach();
}
__makeNative(platformConfig: ?PlatformConfig) {
this.x.__makeNative(platformConfig);
this.y.__makeNative(platformConfig);
super.__makeNative(platformConfig);
}
}
module.exports = AnimatedValueXY;