Support color animation with native driver for Android

Summary:
Adds support for Animated.Color with native driver for Android. Reads the native config for the rbga channel AnimatedNodes, and on update(), converts the values into an integer (0xaarrggbb)

Followup changes will include support for iOS and platform colors.

Changelog:
[Android][Added] - Support running animations with AnimatedColor with native driver

Reviewed By: javache

Differential Revision: D33833600

fbshipit-source-id: 2bf05c9715b603cf014ace09e9308b2bfd67f30a
This commit is contained in:
Genki Kondo
2022-01-29 13:51:41 -08:00
committed by Facebook GitHub Bot
parent 0ab0c5a42e
commit 3f49e6763e
10 changed files with 128 additions and 10 deletions
@@ -28,6 +28,7 @@ rn_android_library(
react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
react_native_target("java/com/facebook/react/views/view:view"),
],
exported_deps = [react_native_root_target(":FBReactNativeSpec")],
)
@@ -0,0 +1,66 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.animated;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.views.view.ColorUtil;
/** Animated node that represents a color. */
/*package*/ class ColorAnimatedNode extends AnimatedNode {
private final NativeAnimatedNodesManager mNativeAnimatedNodesManager;
private final int mRNodeId;
private final int mGNodeId;
private final int mBNodeId;
private final int mANodeId;
private int mColor;
public ColorAnimatedNode(
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
mRNodeId = config.getInt("r");
mGNodeId = config.getInt("g");
mBNodeId = config.getInt("b");
mANodeId = config.getInt("a");
// TODO (T110930421): Support platform color
}
public int getColor() {
return mColor;
}
@Override
public void update() {
AnimatedNode rNode = mNativeAnimatedNodesManager.getNodeById(mRNodeId);
AnimatedNode gNode = mNativeAnimatedNodesManager.getNodeById(mGNodeId);
AnimatedNode bNode = mNativeAnimatedNodesManager.getNodeById(mBNodeId);
AnimatedNode aNode = mNativeAnimatedNodesManager.getNodeById(mANodeId);
double r = ((ValueAnimatedNode) rNode).getValue();
double g = ((ValueAnimatedNode) gNode).getValue();
double b = ((ValueAnimatedNode) bNode).getValue();
double a = ((ValueAnimatedNode) aNode).getValue();
mColor = ColorUtil.normalize(r, g, b, a);
}
@Override
public String prettyPrint() {
return "ColorAnimatedNode["
+ mTag
+ "]: r: "
+ mRNodeId
+ " g: "
+ mGNodeId
+ " b: "
+ mBNodeId
+ " a: "
+ mANodeId;
}
}
@@ -129,6 +129,8 @@ import java.util.Queue;
node = new StyleAnimatedNode(config, this);
} else if ("value".equals(type)) {
node = new ValueAnimatedNode(config);
} else if ("color".equals(type)) {
node = new ColorAnimatedNode(config, this);
} else if ("props".equals(type)) {
node = new PropsAnimatedNode(config, this);
} else if ("interpolation".equals(type)) {
@@ -105,6 +105,8 @@ import java.util.Map;
} else {
mPropMap.putDouble(entry.getKey(), ((ValueAnimatedNode) node).getValue());
}
} else if (node instanceof ColorAnimatedNode) {
mPropMap.putInt(entry.getKey(), ((ColorAnimatedNode) node).getColor());
} else {
throw new IllegalArgumentException(
"Unsupported type of node used in property node " + node.getClass());
@@ -43,6 +43,8 @@ import java.util.Map;
((TransformAnimatedNode) node).collectViewUpdates(propsMap);
} else if (node instanceof ValueAnimatedNode) {
propsMap.putDouble(entry.getKey(), ((ValueAnimatedNode) node).getValue());
} else if (node instanceof ColorAnimatedNode) {
propsMap.putInt(entry.getKey(), ((ColorAnimatedNode) node).getColor());
} else {
throw new IllegalArgumentException(
"Unsupported type of node used in property node " + node.getClass());
@@ -39,6 +39,7 @@ public class ColorUtil {
/**
* Gets the opacity from a color. Inspired by Android ColorDrawable.
*
* @param color color to get opacity from
* @return opacity expressed by one of PixelFormat constants
*/
public static int getOpacityFromColor(int color) {
@@ -51,4 +52,22 @@ public class ColorUtil {
return PixelFormat.TRANSLUCENT;
}
}
/**
* Converts individual {r, g, b, a} channel values to a single integer representation of the color
* as 0xAARRGGBB.
*
* @param r red channel value, [0, 255]
* @param g green channel value, [0, 255]
* @param b blue channel value, [0, 255]
* @param a alpha channel value, [0, 1]
* @return integer representation of the color as 0xAARRGGBB
*/
public static int normalize(double r, double g, double b, double a) {
return (clamp255(a * 255) << 24) | (clamp255(r) << 16) | (clamp255(g) << 8) | clamp255(b);
}
private static int clamp255(double value) {
return Math.max(0, Math.min(255, (int) Math.round(value)));
}
}