Skip to content

Commit e8c9c94

Browse files
tomekzawMatiPl01
authored andcommitted
Add support for remaining synchronous props on Android (#7962)
## Summary This PR adds support for the animating remaining synchronous props using a fast path on Android (which is still hidden behind `ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS` static Reanimated feature flag). After this change, all props from [NativeAnimatedAllowlist.js](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Animated/NativeAnimatedAllowlist.js) are supported, except for `scaleX`, `scaleY`, `translateX`, `translateY` (which are deprecated outside of `transform`), `shadowOffset`, `shadowOpacity` (which are not supported on Android at all) and `color` (which doesn't work for some unknown reason). Even though `elevation` and `zIndex` are supposed to be integers, I decided to pass them as double to achieve the same behavior as when animating them via `ShadowTree`. ## TODO * Add support other `react-native` props, e.g. `filter`, `outlineColor`, `placeholderTextColor` etc. * Add support for other `react-native-svg` props, e.g. `fill`, `stroke` etc. ## Test plan Enable `ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS` static feature flag <details> <summary> `tintColor` </summary> ```tsx import React, { useEffect } from 'react'; import { StyleSheet, View } from 'react-native'; import Animated, { interpolateColor, useAnimatedStyle, useSharedValue, withRepeat, withTiming, } from 'react-native-reanimated'; export default function EmptyExample() { const sv = useSharedValue(0); useEffect(() => { sv.value = 0; sv.value = withRepeat(withTiming(1, { duration: 500 }), -1, true); }, [sv]); const animatedStyle = useAnimatedStyle(() => { return { tintColor: interpolateColor(sv.value, [0, 1], ['red', 'blue']), }; }); return ( <View style={styles.container}> <Animated.Image style={[{ width: 50, height: 50 }, animatedStyle]} source={{ uri: 'https://raw.githubusercontent.com/facebook/react-native/refs/heads/main/packages/rn-tester/js/assets/uie_thumb_normal%402x.png', }} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, }); ``` </details>
1 parent bc61dd3 commit e8c9c94

File tree

4 files changed

+269
-20
lines changed

4 files changed

+269
-20
lines changed

apps/common-app/src/apps/reanimated/examples/ColorExample.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ export default function ColorExample() {
3434
};
3535
});
3636

37+
const style5 = useAnimatedStyle(() => {
38+
return { tintColor: makeColor(sv.value) };
39+
});
40+
3741
// TODO: textDecorationColor, tintColor, textShadowColor, overlayColor
3842

3943
const handleToggle = () => {
@@ -47,6 +51,10 @@ export default function ColorExample() {
4751
<Animated.View style={[styles.box2, style2]} />
4852
<Animated.Text style={[styles.text3, style3]}>Reanimated</Animated.Text>
4953
<Animated.View style={[styles.box4, style4]} />
54+
<Animated.Image
55+
style={[styles.image5, style5]}
56+
source={require('./assets/logo.png')}
57+
/>
5058
<View style={styles.buttons}>
5159
<Button onPress={handleToggle} title="Toggle shared value" />
5260
</View>
@@ -91,8 +99,13 @@ const styles = StyleSheet.create({
9199
shadowOpacity: 1,
92100
shadowColor: 'black',
93101
elevation: 20,
102+
marginBottom: 50,
103+
},
104+
image5: {
105+
width: 150,
106+
height: 120,
94107
},
95108
buttons: {
96-
marginTop: 50,
109+
marginTop: 20,
97110
},
98111
});
31.7 KB
Loading

packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp

Lines changed: 174 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -674,24 +674,74 @@ void ReanimatedModuleProxy::performOperations() {
674674
if constexpr (StaticFeatureFlags::getFlag(
675675
"ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS")) {
676676
static const std::unordered_set<std::string> synchronousProps = {
677-
"transform",
678677
"opacity",
679-
"borderRadius",
678+
"elevation",
679+
"zIndex",
680+
// "shadowOpacity", // not supported on Android
681+
// "shadowRadius", // not supported on Android
680682
"backgroundColor",
681-
"borderColor",
682683
// "color", // TODO: fix animating color of Animated.Text
684+
"tintColor",
685+
"borderRadius",
686+
"borderTopLeftRadius",
687+
"borderTopRightRadius",
688+
"borderTopStartRadius",
689+
"borderTopEndRadius",
690+
"borderBottomLeftRadius",
691+
"borderBottomRightRadius",
692+
"borderBottomStartRadius",
693+
"borderBottomEndRadius",
694+
"borderStartStartRadius",
695+
"borderStartEndRadius",
696+
"borderEndStartRadius",
697+
"borderEndEndRadius",
698+
"borderColor",
699+
"borderTopColor",
700+
"borderBottomColor",
701+
"borderLeftColor",
702+
"borderRightColor",
703+
"borderStartColor",
704+
"borderEndColor",
705+
"transform",
683706
};
684707

685708
// NOTE: Keep in sync with NativeProxy.java
686709
static constexpr auto CMD_START_OF_VIEW = 1;
687710
static constexpr auto CMD_START_OF_TRANSFORM = 2;
688711
static constexpr auto CMD_END_OF_TRANSFORM = 3;
689712
static constexpr auto CMD_END_OF_VIEW = 4;
713+
690714
static constexpr auto CMD_OPACITY = 10;
691-
static constexpr auto CMD_BORDER_RADIUS = 11;
692-
static constexpr auto CMD_BACKGROUND_COLOR = 12;
693-
static constexpr auto CMD_BORDER_COLOR = 13;
694-
static constexpr auto CMD_COLOR = 14;
715+
static constexpr auto CMD_ELEVATION = 11;
716+
static constexpr auto CMD_Z_INDEX = 12;
717+
static constexpr auto CMD_SHADOW_OPACITY = 13;
718+
static constexpr auto CMD_SHADOW_RADIUS = 14;
719+
static constexpr auto CMD_BACKGROUND_COLOR = 15;
720+
static constexpr auto CMD_COLOR = 16;
721+
static constexpr auto CMD_TINT_COLOR = 17;
722+
723+
static constexpr auto CMD_BORDER_RADIUS = 20;
724+
static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
725+
static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
726+
static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
727+
static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
728+
static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
729+
static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
730+
static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
731+
static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
732+
static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
733+
static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
734+
static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
735+
static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
736+
737+
static constexpr auto CMD_BORDER_COLOR = 40;
738+
static constexpr auto CMD_BORDER_TOP_COLOR = 41;
739+
static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
740+
static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
741+
static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
742+
static constexpr auto CMD_BORDER_START_COLOR = 45;
743+
static constexpr auto CMD_BORDER_END_COLOR = 46;
744+
695745
static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
696746
static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
697747
static constexpr auto CMD_TRANSFORM_SCALE = 102;
@@ -705,6 +755,7 @@ void ReanimatedModuleProxy::performOperations() {
705755
static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
706756
static constexpr auto CMD_TRANSFORM_MATRIX = 111;
707757
static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
758+
708759
static constexpr auto CMD_UNIT_DEG = 200;
709760
static constexpr auto CMD_UNIT_RAD = 201;
710761
static constexpr auto CMD_UNIT_PX = 202;
@@ -713,46 +764,134 @@ void ReanimatedModuleProxy::performOperations() {
713764
const auto propNameToCommand = [](const std::string &name) {
714765
if (name == "opacity")
715766
return CMD_OPACITY;
716-
if (name == "borderRadius")
717-
return CMD_BORDER_RADIUS;
767+
768+
if (name == "elevation")
769+
return CMD_ELEVATION;
770+
771+
if (name == "zIndex")
772+
return CMD_Z_INDEX;
773+
774+
if (name == "shadowOpacity")
775+
return CMD_SHADOW_OPACITY;
776+
777+
if (name == "shadowRadius")
778+
return CMD_SHADOW_RADIUS;
779+
718780
if (name == "backgroundColor")
719781
return CMD_BACKGROUND_COLOR;
720-
if (name == "borderColor")
721-
return CMD_BORDER_COLOR;
782+
722783
if (name == "color")
723784
return CMD_COLOR;
785+
786+
if (name == "tintColor")
787+
return CMD_TINT_COLOR;
788+
789+
if (name == "borderRadius")
790+
return CMD_BORDER_RADIUS;
791+
792+
if (name == "borderTopLeftRadius")
793+
return CMD_BORDER_TOP_LEFT_RADIUS;
794+
795+
if (name == "borderTopRightRadius")
796+
return CMD_BORDER_TOP_RIGHT_RADIUS;
797+
798+
if (name == "borderTopStartRadius")
799+
return CMD_BORDER_TOP_START_RADIUS;
800+
801+
if (name == "borderTopEndRadius")
802+
return CMD_BORDER_TOP_END_RADIUS;
803+
804+
if (name == "borderBottomLeftRadius")
805+
return CMD_BORDER_BOTTOM_LEFT_RADIUS;
806+
807+
if (name == "borderBottomRightRadius")
808+
return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
809+
810+
if (name == "borderBottomStartRadius")
811+
return CMD_BORDER_BOTTOM_START_RADIUS;
812+
813+
if (name == "borderBottomEndRadius")
814+
return CMD_BORDER_BOTTOM_END_RADIUS;
815+
816+
if (name == "borderStartStartRadius")
817+
return CMD_BORDER_START_START_RADIUS;
818+
819+
if (name == "borderStartEndRadius")
820+
return CMD_BORDER_START_END_RADIUS;
821+
822+
if (name == "borderEndStartRadius")
823+
return CMD_BORDER_END_START_RADIUS;
824+
825+
if (name == "borderEndEndRadius")
826+
return CMD_BORDER_END_END_RADIUS;
827+
828+
if (name == "borderColor")
829+
return CMD_BORDER_COLOR;
830+
831+
if (name == "borderTopColor")
832+
return CMD_BORDER_TOP_COLOR;
833+
834+
if (name == "borderBottomColor")
835+
return CMD_BORDER_BOTTOM_COLOR;
836+
837+
if (name == "borderLeftColor")
838+
return CMD_BORDER_LEFT_COLOR;
839+
840+
if (name == "borderRightColor")
841+
return CMD_BORDER_RIGHT_COLOR;
842+
843+
if (name == "borderStartColor")
844+
return CMD_BORDER_START_COLOR;
845+
846+
if (name == "borderEndColor")
847+
return CMD_BORDER_END_COLOR;
848+
724849
if (name == "transform")
725850
return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
851+
726852
throw std::runtime_error("Unsupported style: " + name);
727853
};
728854

729855
const auto transformNameToCommand = [](const std::string &name) {
730856
if (name == "translateX")
731857
return CMD_TRANSFORM_TRANSLATE_X;
858+
732859
if (name == "translateY")
733860
return CMD_TRANSFORM_TRANSLATE_Y;
861+
734862
if (name == "scale")
735863
return CMD_TRANSFORM_SCALE;
864+
736865
if (name == "scaleX")
737866
return CMD_TRANSFORM_SCALE_X;
867+
738868
if (name == "scaleY")
739869
return CMD_TRANSFORM_SCALE_Y;
870+
740871
if (name == "rotate")
741872
return CMD_TRANSFORM_ROTATE;
873+
742874
if (name == "rotateX")
743875
return CMD_TRANSFORM_ROTATE_X;
876+
744877
if (name == "rotateY")
745878
return CMD_TRANSFORM_ROTATE_Y;
879+
746880
if (name == "rotateZ")
747881
return CMD_TRANSFORM_ROTATE_Z;
882+
748883
if (name == "skewX")
749884
return CMD_TRANSFORM_SKEW_X;
885+
750886
if (name == "skewY")
751887
return CMD_TRANSFORM_SKEW_Y;
888+
752889
if (name == "matrix")
753890
return CMD_TRANSFORM_MATRIX;
891+
754892
if (name == "perspective")
755893
return CMD_TRANSFORM_PERSPECTIVE;
894+
756895
throw std::runtime_error("Unsupported transform: " + name);
757896
};
758897

@@ -787,14 +926,37 @@ void ReanimatedModuleProxy::performOperations() {
787926
const auto command = propNameToCommand(key.getString());
788927
switch (command) {
789928
case CMD_OPACITY:
929+
case CMD_ELEVATION:
930+
case CMD_Z_INDEX:
931+
case CMD_SHADOW_OPACITY:
932+
case CMD_SHADOW_RADIUS:
790933
case CMD_BORDER_RADIUS:
934+
case CMD_BORDER_TOP_LEFT_RADIUS:
935+
case CMD_BORDER_TOP_RIGHT_RADIUS:
936+
case CMD_BORDER_TOP_START_RADIUS:
937+
case CMD_BORDER_TOP_END_RADIUS:
938+
case CMD_BORDER_BOTTOM_LEFT_RADIUS:
939+
case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
940+
case CMD_BORDER_BOTTOM_START_RADIUS:
941+
case CMD_BORDER_BOTTOM_END_RADIUS:
942+
case CMD_BORDER_START_START_RADIUS:
943+
case CMD_BORDER_START_END_RADIUS:
944+
case CMD_BORDER_END_START_RADIUS:
945+
case CMD_BORDER_END_END_RADIUS:
791946
intBuffer.push_back(command);
792947
doubleBuffer.push_back(value.asDouble());
793948
break;
794949

795950
case CMD_BACKGROUND_COLOR:
796-
case CMD_BORDER_COLOR:
797951
case CMD_COLOR:
952+
case CMD_TINT_COLOR:
953+
case CMD_BORDER_COLOR:
954+
case CMD_BORDER_TOP_COLOR:
955+
case CMD_BORDER_BOTTOM_COLOR:
956+
case CMD_BORDER_LEFT_COLOR:
957+
case CMD_BORDER_RIGHT_COLOR:
958+
case CMD_BORDER_START_COLOR:
959+
case CMD_BORDER_END_COLOR:
798960
intBuffer.push_back(command);
799961
intBuffer.push_back(value.asInt());
800962
break;

0 commit comments

Comments
 (0)