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:
Родитель
841793a281
Коммит
73191edb72
|
@ -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,12 +150,9 @@ 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) {
|
||||
this.__makeNative();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.nativeColor || (config && config.useNativeDriver)) {
|
||||
this.__makeNative();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче