Skip to content

Commit

Permalink
Support animating text color with native driver
Browse files Browse the repository at this point in the history
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
  • Loading branch information
genkikondo authored and facebook-github-bot committed Mar 7, 2022
1 parent e1dc9a7 commit 87cdb60
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
package com.facebook.react.uimanager;

import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import java.util.Map;

/**
Expand Down Expand Up @@ -85,11 +87,16 @@ public ReadableMap getMap(String key) {
return mBackingMap.getMap(key);
}

@Nullable
@NonNull
public Dynamic getDynamic(String key) {
return mBackingMap.getDynamic(key);
}

@NonNull
public ReadableType getType(String key) {
return mBackingMap.getType(key);
}

@Override
public String toString() {
return "{ " + getClass().getSimpleName() + ": " + mBackingMap.toString() + " }";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ public void setAccessible(ReactTextView view, boolean accessible) {
view.setFocusable(accessible);
}

@ReactProp(name = ViewProps.COLOR, customType = "Color")
public void setColor(ReactTextView view, int color) {
/**
* This is needed for natively driven animations for text color. Typically, {@link
* ReactTextView#setText} is called via {@link ReactTextViewManager#updateExtraData}, but
* natively animated color changes bypass render and layout pass via direct call to {@link
* SurfaceMountingManager#updateProps} from {@link UIManager#synchronouslyUpdateViewOnUIThread}.
*/
Spannable spannable = view.getSpanned();
if (spannable != null) {
spannable.setSpan(
new ReactForegroundColorSpan(color),
0,
spannable.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
view.setText(spannable);
}
}

// maxLines can only be set in master view (block), doesn't really make sense to set in a span
@ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = ViewDefaults.NUMBER_OF_LINES)
public void setNumberOfLines(ReactTextView view, int numberOfLines) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
Expand All @@ -21,6 +22,7 @@
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.StateWrapper;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.yoga.YogaMeasureMode;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -113,6 +115,20 @@ public Object updateState(
Spannable spanned =
TextLayoutManager.getOrCreateSpannableForText(
view.getContext(), attributedString, mReactTextViewManagerCallback);

/**
* For natively driven animations for text color, on mount, {@link
* UIManager#synchronouslyUpdateViewOnUIThread} may be called before updateState, in which case
* the ReactStylesDiffMap will contain the color.
*/
if (props.hasKey(ViewProps.COLOR) && props.getType(ViewProps.COLOR) == ReadableType.Number) {
spanned.setSpan(
new ReactForegroundColorSpan(props.getInt(ViewProps.COLOR, 0)),
0,
spanned.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}

view.setSpanned(spanned);

int textBreakStrategy =
Expand Down

0 comments on commit 87cdb60

Please sign in to comment.