Skip to content

Commit 44a96ac

Browse files
NickGerlemankelset
authored andcommittedApr 19, 2023
Minimize EditText Spans 5/9: Strikethrough and Underline (#36544)
Summary: Pull Request resolved: #36544 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]( #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 Reviewed By: rshest Differential Revision: D44240778 fbshipit-source-id: d564dfc0121057a5e3b09bb71b8f5662e28be17e
1 parent ab6be34 commit 44a96ac

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed
 

‎ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java

+31
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;
@@ -54,8 +55,10 @@
5455
import com.facebook.react.views.text.ReactBackgroundColorSpan;
5556
import com.facebook.react.views.text.ReactForegroundColorSpan;
5657
import com.facebook.react.views.text.ReactSpan;
58+
import com.facebook.react.views.text.ReactStrikethroughSpan;
5759
import com.facebook.react.views.text.ReactTextUpdate;
5860
import com.facebook.react.views.text.ReactTypefaceUtils;
61+
import com.facebook.react.views.text.ReactUnderlineSpan;
5962
import com.facebook.react.views.text.TextAttributes;
6063
import com.facebook.react.views.text.TextInlineImageSpan;
6164
import com.facebook.react.views.text.TextLayoutManager;
@@ -668,6 +671,26 @@ public boolean test(ReactForegroundColorSpan span) {
668671
return span.getForegroundColor() == getCurrentTextColor();
669672
}
670673
});
674+
675+
stripSpansOfKind(
676+
sb,
677+
ReactStrikethroughSpan.class,
678+
new SpanPredicate<ReactStrikethroughSpan>() {
679+
@Override
680+
public boolean test(ReactStrikethroughSpan span) {
681+
return (getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0;
682+
}
683+
});
684+
685+
stripSpansOfKind(
686+
sb,
687+
ReactUnderlineSpan.class,
688+
new SpanPredicate<ReactUnderlineSpan>() {
689+
@Override
690+
public boolean test(ReactUnderlineSpan span) {
691+
return (getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0;
692+
}
693+
});
671694
}
672695

673696
private <T> void stripSpansOfKind(
@@ -701,6 +724,14 @@ private void restoreStyleEquivalentSpans(SpannableStringBuilder workingText) {
701724
spans.add(new ReactBackgroundColorSpan(backgroundColor));
702725
}
703726

727+
if ((getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
728+
spans.add(new ReactStrikethroughSpan());
729+
}
730+
731+
if ((getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0) {
732+
spans.add(new ReactUnderlineSpan());
733+
}
734+
704735
for (Object span : spans) {
705736
workingText.setSpan(span, 0, workingText.length(), spanFlags);
706737
}

‎ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java

+15
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;
@@ -913,6 +914,20 @@ public void setAutoFocus(ReactEditText view, boolean autoFocus) {
913914
view.setAutoFocus(autoFocus);
914915
}
915916

917+
@ReactProp(name = ViewProps.TEXT_DECORATION_LINE)
918+
public void setTextDecorationLine(ReactEditText view, @Nullable String textDecorationLineString) {
919+
view.setPaintFlags(
920+
view.getPaintFlags() & ~(Paint.STRIKE_THRU_TEXT_FLAG | Paint.UNDERLINE_TEXT_FLAG));
921+
922+
for (String token : textDecorationLineString.split(" ")) {
923+
if (token.equals("underline")) {
924+
view.setPaintFlags(view.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
925+
} else if (token.equals("line-through")) {
926+
view.setPaintFlags(view.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
927+
}
928+
}
929+
}
930+
916931
@ReactPropGroup(
917932
names = {
918933
ViewProps.BORDER_WIDTH,

0 commit comments

Comments
 (0)
Please sign in to comment.