Skip to content

Commit cb42049

Browse files
genkikondofacebook-github-bot
authored andcommitted
Support platform color with AnimatedColor on Android
Summary: Adds support for platform colors in AnimatedColor. Passes the processed native color object to the native ColorAnimatedNode via the native config; ColorAnimatedNode then uses ColorPropConverter.getColor to resolve the resource path. Note: setting a platform color via setValue on an existing AnimatedColor is not supported yet Changelog: [Android][Added] - Support platform color with AnimatedColor Reviewed By: yungsters Differential Revision: D33922266 fbshipit-source-id: 04d39a5ce0872b31d06ffbd4639d2f2213cf3314
1 parent 3552ff0 commit cb42049

File tree

3 files changed

+92
-34
lines changed

3 files changed

+92
-34
lines changed

Libraries/Animated/nodes/AnimatedColor.js

+53-22
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export default class AnimatedColor extends AnimatedWithChildren {
9191
g: AnimatedValue;
9292
b: AnimatedValue;
9393
a: AnimatedValue;
94+
nativeColor: Object;
9495
_listeners: {
9596
[key: string]: {
9697
r: string,
@@ -105,8 +106,16 @@ export default class AnimatedColor extends AnimatedWithChildren {
105106
constructor(valueIn?: ?(RgbaValue | RgbaAnimatedValue | ColorValue)) {
106107
super();
107108
let value: RgbaValue | RgbaAnimatedValue | ColorValue =
108-
valueIn || defaultColor;
109+
valueIn ?? defaultColor;
110+
this.setValue(value);
111+
this._listeners = {};
112+
}
109113

114+
/**
115+
* Directly set the value. This will stop any animations running on the value
116+
* and update all the bound properties.
117+
*/
118+
setValue(value: RgbaValue | RgbaAnimatedValue | ColorValue): void {
110119
if (isRgbaAnimatedValue(value)) {
111120
// $FlowIgnore[incompatible-cast] - Type is verified above
112121
const rgbaAnimatedValue: RgbaAnimatedValue = (value: RgbaAnimatedValue);
@@ -118,37 +127,58 @@ export default class AnimatedColor extends AnimatedWithChildren {
118127
// Handle potential parsable string color or platform color object
119128
if (!isRgbaValue(value)) {
120129
// $FlowIgnore[incompatible-cast] - Type is verified via conditionals
121-
value = processColor((value: ColorValue)) || {r: 0, g: 0, b: 0, a: 1.0};
122-
// TODO: support platform color
130+
value = processColor((value: ColorValue)) ?? defaultColor;
123131
}
124132

125-
// $FlowIgnore[incompatible-cast] - Type is verified via conditionals
126-
const rgbaValue: RgbaValue = (value: RgbaValue);
127-
this.r = new AnimatedValue(rgbaValue.r);
128-
this.g = new AnimatedValue(rgbaValue.g);
129-
this.b = new AnimatedValue(rgbaValue.b);
130-
this.a = new AnimatedValue(rgbaValue.a);
131-
}
132-
this._listeners = {};
133-
}
133+
if (!isRgbaValue(value)) {
134+
// We are using a platform color
135+
this.nativeColor = value;
136+
value = defaultColor;
137+
}
134138

135-
/**
136-
* Directly set the value. This will stop any animations running on the value
137-
* and update all the bound properties.
138-
*/
139-
setValue(value: {r: number, g: number, b: number, a: number, ...}): void {
140-
this.r.setValue(value.r);
141-
this.g.setValue(value.g);
142-
this.b.setValue(value.b);
143-
this.a.setValue(value.a);
139+
if (isRgbaValue(value)) {
140+
// $FlowIgnore[incompatible-cast] - Type is verified via conditionals
141+
const rgbaValue: RgbaValue = (value: RgbaValue);
142+
143+
if (this.r) {
144+
this.r.setValue(rgbaValue.r);
145+
} else {
146+
this.r = new AnimatedValue(rgbaValue.r);
147+
}
148+
149+
if (this.g) {
150+
this.g.setValue(rgbaValue.g);
151+
} else {
152+
this.g = new AnimatedValue(rgbaValue.g);
153+
}
154+
155+
if (this.b) {
156+
this.b.setValue(rgbaValue.b);
157+
} else {
158+
this.b = new AnimatedValue(rgbaValue.b);
159+
}
160+
161+
if (this.a) {
162+
this.a.setValue(rgbaValue.a);
163+
} else {
164+
this.a = new AnimatedValue(rgbaValue.a);
165+
}
166+
}
167+
168+
if (this.nativeColor) {
169+
this.__makeNative();
170+
// TODO (T111170195): In order to support setValue() with a platform color, update the
171+
// native AnimatedNode (if it exists) with a new config.
172+
}
173+
}
144174
}
145175

146176
/**
147177
* Sets an offset that is applied on top of whatever value is set, whether
148178
* via `setValue`, an animation, or `Animated.event`. Useful for compensating
149179
* things like the start of a pan gesture.
150180
*/
151-
setOffset(offset: {r: number, g: number, b: number, a: number, ...}): void {
181+
setOffset(offset: RgbaValue): void {
152182
this.r.setOffset(offset.r);
153183
this.g.setOffset(offset.g);
154184
this.b.setOffset(offset.b);
@@ -280,6 +310,7 @@ export default class AnimatedColor extends AnimatedWithChildren {
280310
g: this.g.__getNativeTag(),
281311
b: this.b.__getNativeTag(),
282312
a: this.a.__getNativeTag(),
313+
nativeColor: this.nativeColor,
283314
};
284315
}
285316
}

ReactAndroid/src/main/java/com/facebook/react/animated/ColorAnimatedNode.java

+38-11
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,34 @@
77

88
package com.facebook.react.animated;
99

10+
import android.graphics.Color;
11+
import com.facebook.react.bridge.ColorPropConverter;
12+
import com.facebook.react.bridge.ReactApplicationContext;
1013
import com.facebook.react.bridge.ReadableMap;
1114
import com.facebook.react.views.view.ColorUtil;
1215

1316
/** Animated node that represents a color. */
1417
/*package*/ class ColorAnimatedNode extends AnimatedNode {
1518

1619
private final NativeAnimatedNodesManager mNativeAnimatedNodesManager;
20+
private final ReactApplicationContext mReactApplicationContext;
1721
private final int mRNodeId;
1822
private final int mGNodeId;
1923
private final int mBNodeId;
2024
private final int mANodeId;
2125
private int mColor;
2226

2327
public ColorAnimatedNode(
24-
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
28+
ReadableMap config,
29+
NativeAnimatedNodesManager nativeAnimatedNodesManager,
30+
ReactApplicationContext reactApplicationContext) {
2531
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
32+
mReactApplicationContext = reactApplicationContext;
2633
mRNodeId = config.getInt("r");
2734
mGNodeId = config.getInt("g");
2835
mBNodeId = config.getInt("b");
2936
mANodeId = config.getInt("a");
30-
31-
// TODO (T110930421): Support platform color
37+
setNativeColor(config.getMap("nativeColor"));
3238
}
3339

3440
public int getColor() {
@@ -37,15 +43,15 @@ public int getColor() {
3743

3844
@Override
3945
public void update() {
40-
AnimatedNode rNode = mNativeAnimatedNodesManager.getNodeById(mRNodeId);
41-
AnimatedNode gNode = mNativeAnimatedNodesManager.getNodeById(mGNodeId);
42-
AnimatedNode bNode = mNativeAnimatedNodesManager.getNodeById(mBNodeId);
43-
AnimatedNode aNode = mNativeAnimatedNodesManager.getNodeById(mANodeId);
46+
ValueAnimatedNode rNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mRNodeId);
47+
ValueAnimatedNode gNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mGNodeId);
48+
ValueAnimatedNode bNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mBNodeId);
49+
ValueAnimatedNode aNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mANodeId);
4450

45-
double r = ((ValueAnimatedNode) rNode).getValue();
46-
double g = ((ValueAnimatedNode) gNode).getValue();
47-
double b = ((ValueAnimatedNode) bNode).getValue();
48-
double a = ((ValueAnimatedNode) aNode).getValue();
51+
double r = rNode.getValue();
52+
double g = gNode.getValue();
53+
double b = bNode.getValue();
54+
double a = aNode.getValue();
4955

5056
mColor = ColorUtil.normalize(r, g, b, a);
5157
}
@@ -63,4 +69,25 @@ public String prettyPrint() {
6369
+ " a: "
6470
+ mANodeId;
6571
}
72+
73+
private void setNativeColor(ReadableMap nativeColor) {
74+
if (nativeColor == null) {
75+
return;
76+
}
77+
78+
int color =
79+
ColorPropConverter.getColor(nativeColor, mReactApplicationContext.getCurrentActivity());
80+
81+
ValueAnimatedNode rNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mRNodeId);
82+
ValueAnimatedNode gNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mGNodeId);
83+
ValueAnimatedNode bNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mBNodeId);
84+
ValueAnimatedNode aNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mANodeId);
85+
86+
rNode.mValue = Color.red(color);
87+
gNode.mValue = Color.green(color);
88+
bNode.mValue = Color.blue(color);
89+
aNode.mValue = Color.alpha(color) / 255.0;
90+
91+
update();
92+
}
6693
}

ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public void createAnimatedNode(int tag, ReadableMap config) {
130130
} else if ("value".equals(type)) {
131131
node = new ValueAnimatedNode(config);
132132
} else if ("color".equals(type)) {
133-
node = new ColorAnimatedNode(config, this);
133+
node = new ColorAnimatedNode(config, this, mReactApplicationContext);
134134
} else if ("props".equals(type)) {
135135
node = new PropsAnimatedNode(config, this);
136136
} else if ("interpolation".equals(type)) {

0 commit comments

Comments
 (0)