Skip to content

Commit 8190f33

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Minimize EditText Spans 5/N: Strikethrough and Underline
Summary: This is part of a series of changes to minimize the number of spans committed to EditText, as a mitigation for platform issues on Samsung devices. See this [GitHub thread]( facebook#35936 (comment)) for greater context on the platform behavior. This change makes us apply strikethrough and underline as paint flags to the underlying EditText, instead of just the spans. We then opt ReactUnderlineSpan and ReactStrikethroughSpan into being strippable. This does actually create visual behavior changes, where child text will inherit any underline or strikethrough of the root EditText (including if the child specifies `textDecorationLine: "none"`. The new behavior is consistent with both iOS and web though, so it seems like more of a bugfix than a regression. Changelog: [Android][Fixed] - Minimize Spans 5/N: Strikethrough and Underline Differential Revision: https://www.internalfb.com/diff/D44240778?entry_point=27 fbshipit-source-id: c6652a5aebc67facc4311c85cf3ca1f3d76572db
1 parent 5cbf599 commit 8190f33

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import android.content.Context;
1414
import android.graphics.Color;
15+
import android.graphics.Paint;
1516
import android.graphics.Rect;
1617
import android.graphics.Typeface;
1718
import android.graphics.drawable.Drawable;
@@ -53,6 +54,8 @@
5354
import com.facebook.react.views.text.ReactAbsoluteSizeSpan;
5455
import com.facebook.react.views.text.ReactBackgroundColorSpan;
5556
import com.facebook.react.views.text.ReactForegroundColorSpan;
57+
import com.facebook.react.views.text.ReactStrikethroughSpan;
58+
import com.facebook.react.views.text.ReactUnderlineSpan;
5659
import com.facebook.react.views.text.ReactSpan;
5760
import com.facebook.react.views.text.ReactTextUpdate;
5861
import com.facebook.react.views.text.ReactTypefaceUtils;
@@ -703,6 +706,26 @@ public boolean test(ReactForegroundColorSpan span) {
703706
return span.getForegroundColor() == getCurrentTextColor();
704707
}
705708
});
709+
710+
stripSpansOfKind(
711+
sb,
712+
ReactStrikethroughSpan.class,
713+
new SpanPredicate<ReactStrikethroughSpan>() {
714+
@Override
715+
public boolean test(ReactStrikethroughSpan span) {
716+
return (getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0;
717+
}
718+
});
719+
720+
stripSpansOfKind(
721+
sb,
722+
ReactUnderlineSpan.class,
723+
new SpanPredicate<ReactUnderlineSpan>() {
724+
@Override
725+
public boolean test(ReactUnderlineSpan span) {
726+
return (getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0;
727+
}
728+
});
706729
}
707730

708731
private <T> void stripSpansOfKind(
@@ -749,6 +772,14 @@ private void restoreStyleEquivalentSpans(SpannableStringBuilder workingText) {
749772
spans.add(new ReactBackgroundColorSpan(backgroundColor));
750773
}
751774

775+
if ((getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
776+
spans.add(new ReactStrikethroughSpan());
777+
}
778+
779+
if ((getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0) {
780+
spans.add(new ReactUnderlineSpan());
781+
}
782+
752783
for (Object span : spans) {
753784
workingText.setSpan(span, 0, workingText.length(), spanFlags);
754785
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import android.content.res.ColorStateList;
1414
import android.graphics.BlendMode;
1515
import android.graphics.BlendModeColorFilter;
16+
import android.graphics.Paint;
1617
import android.graphics.PorterDuff;
1718
import android.graphics.drawable.Drawable;
1819
import android.os.Build;
@@ -935,6 +936,20 @@ public void setAutoFocus(ReactEditText view, boolean autoFocus) {
935936
view.setAutoFocus(autoFocus);
936937
}
937938

939+
@ReactProp(name = ViewProps.TEXT_DECORATION_LINE)
940+
public void setTextDecorationLine(ReactEditText view, @Nullable String textDecorationLineString) {
941+
view.setPaintFlags(
942+
view.getPaintFlags() & ~(Paint.STRIKE_THRU_TEXT_FLAG | Paint.UNDERLINE_TEXT_FLAG));
943+
944+
for (String token : textDecorationLineString.split(" ")) {
945+
if (token.equals("underline")) {
946+
view.setPaintFlags(view.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
947+
} else if (token.equals("line-through")) {
948+
view.setPaintFlags(view.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
949+
}
950+
}
951+
}
952+
938953
@ReactPropGroup(
939954
names = {
940955
ViewProps.BORDER_WIDTH,

0 commit comments

Comments
 (0)