Skip to content

Commit 87cdb60

Browse files
genkikondofacebook-github-bot
authored andcommitted
Support animating text color with native driver
Summary: Typically, ReactTextView#setText is called via ReactTextViewManager#updateExtraData, but natively animated color changes bypass render and layout pass via direct call to SurfaceMountingManager#updateProps from UIManager#synchronouslyUpdateViewOnUIThread. Thus, for animated color changes to get applied, we need to handle the color prop in ReactTextAnchorViewManager. In addition, native driver updates are not synchronized with Fabric's mounting; if the native driver update happens before mount, the update is done in updateState. Changelog: [Android][Added] - Support animating text color with native driver Reviewed By: mdvacca Differential Revision: D34630294 fbshipit-source-id: c0f1e19c801c0e909e84387d623a6556ce6f2d67
1 parent e1dc9a7 commit 87cdb60

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMap.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
package com.facebook.react.uimanager;
99

1010
import android.view.View;
11+
import androidx.annotation.NonNull;
1112
import androidx.annotation.Nullable;
1213
import com.facebook.react.bridge.Dynamic;
1314
import com.facebook.react.bridge.ReadableArray;
1415
import com.facebook.react.bridge.ReadableMap;
16+
import com.facebook.react.bridge.ReadableType;
1517
import java.util.Map;
1618

1719
/**
@@ -85,11 +87,16 @@ public ReadableMap getMap(String key) {
8587
return mBackingMap.getMap(key);
8688
}
8789

88-
@Nullable
90+
@NonNull
8991
public Dynamic getDynamic(String key) {
9092
return mBackingMap.getDynamic(key);
9193
}
9294

95+
@NonNull
96+
public ReadableType getType(String key) {
97+
return mBackingMap.getType(key);
98+
}
99+
93100
@Override
94101
public String toString() {
95102
return "{ " + getClass().getSimpleName() + ": " + mBackingMap.toString() + " }";

ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java

+19
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,25 @@ public void setAccessible(ReactTextView view, boolean accessible) {
4848
view.setFocusable(accessible);
4949
}
5050

51+
@ReactProp(name = ViewProps.COLOR, customType = "Color")
52+
public void setColor(ReactTextView view, int color) {
53+
/**
54+
* This is needed for natively driven animations for text color. Typically, {@link
55+
* ReactTextView#setText} is called via {@link ReactTextViewManager#updateExtraData}, but
56+
* natively animated color changes bypass render and layout pass via direct call to {@link
57+
* SurfaceMountingManager#updateProps} from {@link UIManager#synchronouslyUpdateViewOnUIThread}.
58+
*/
59+
Spannable spannable = view.getSpanned();
60+
if (spannable != null) {
61+
spannable.setSpan(
62+
new ReactForegroundColorSpan(color),
63+
0,
64+
spannable.length(),
65+
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
66+
view.setText(spannable);
67+
}
68+
}
69+
5170
// maxLines can only be set in master view (block), doesn't really make sense to set in a span
5271
@ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = ViewDefaults.NUMBER_OF_LINES)
5372
public void setNumberOfLines(ReactTextView view, int numberOfLines) {

ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java

+16
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import androidx.annotation.Nullable;
1313
import com.facebook.react.bridge.ReadableMap;
1414
import com.facebook.react.bridge.ReadableNativeMap;
15+
import com.facebook.react.bridge.ReadableType;
1516
import com.facebook.react.common.MapBuilder;
1617
import com.facebook.react.common.annotations.VisibleForTesting;
1718
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
@@ -21,6 +22,7 @@
2122
import com.facebook.react.uimanager.ReactStylesDiffMap;
2223
import com.facebook.react.uimanager.StateWrapper;
2324
import com.facebook.react.uimanager.ThemedReactContext;
25+
import com.facebook.react.uimanager.ViewProps;
2426
import com.facebook.yoga.YogaMeasureMode;
2527
import java.util.HashMap;
2628
import java.util.Map;
@@ -113,6 +115,20 @@ public Object updateState(
113115
Spannable spanned =
114116
TextLayoutManager.getOrCreateSpannableForText(
115117
view.getContext(), attributedString, mReactTextViewManagerCallback);
118+
119+
/**
120+
* For natively driven animations for text color, on mount, {@link
121+
* UIManager#synchronouslyUpdateViewOnUIThread} may be called before updateState, in which case
122+
* the ReactStylesDiffMap will contain the color.
123+
*/
124+
if (props.hasKey(ViewProps.COLOR) && props.getType(ViewProps.COLOR) == ReadableType.Number) {
125+
spanned.setSpan(
126+
new ReactForegroundColorSpan(props.getInt(ViewProps.COLOR, 0)),
127+
0,
128+
spanned.length(),
129+
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
130+
}
131+
116132
view.setSpanned(spanned);
117133

118134
int textBreakStrategy =

0 commit comments

Comments
 (0)