Skip to content

Commit

Permalink
Minimize EditText Spans 5/9: Strikethrough and Underline (#36544)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
NickGerleman authored and kelset committed Mar 29, 2023
1 parent 3447fea commit 536ee8b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
Expand Down Expand Up @@ -54,8 +55,10 @@
import com.facebook.react.views.text.ReactBackgroundColorSpan;
import com.facebook.react.views.text.ReactForegroundColorSpan;
import com.facebook.react.views.text.ReactSpan;
import com.facebook.react.views.text.ReactStrikethroughSpan;
import com.facebook.react.views.text.ReactTextUpdate;
import com.facebook.react.views.text.ReactTypefaceUtils;
import com.facebook.react.views.text.ReactUnderlineSpan;
import com.facebook.react.views.text.TextAttributes;
import com.facebook.react.views.text.TextInlineImageSpan;
import com.facebook.react.views.text.TextLayoutManager;
Expand Down Expand Up @@ -703,6 +706,26 @@ public boolean test(ReactForegroundColorSpan span) {
return span.getForegroundColor() == getCurrentTextColor();
}
});

stripSpansOfKind(
sb,
ReactStrikethroughSpan.class,
new SpanPredicate<ReactStrikethroughSpan>() {
@Override
public boolean test(ReactStrikethroughSpan span) {
return (getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0;
}
});

stripSpansOfKind(
sb,
ReactUnderlineSpan.class,
new SpanPredicate<ReactUnderlineSpan>() {
@Override
public boolean test(ReactUnderlineSpan span) {
return (getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0;
}
});
}

private <T> void stripSpansOfKind(
Expand Down Expand Up @@ -736,6 +759,14 @@ private void restoreStyleEquivalentSpans(SpannableStringBuilder workingText) {
spans.add(new ReactBackgroundColorSpan(backgroundColor));
}

if ((getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
spans.add(new ReactStrikethroughSpan());
}

if ((getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0) {
spans.add(new ReactUnderlineSpan());
}

for (Object span : spans) {
workingText.setSpan(span, 0, workingText.length(), spanFlags);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import android.content.res.ColorStateList;
import android.graphics.BlendMode;
import android.graphics.BlendModeColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
Expand Down Expand Up @@ -935,6 +936,20 @@ public void setAutoFocus(ReactEditText view, boolean autoFocus) {
view.setAutoFocus(autoFocus);
}

@ReactProp(name = ViewProps.TEXT_DECORATION_LINE)
public void setTextDecorationLine(ReactEditText view, @Nullable String textDecorationLineString) {
view.setPaintFlags(
view.getPaintFlags() & ~(Paint.STRIKE_THRU_TEXT_FLAG | Paint.UNDERLINE_TEXT_FLAG));

for (String token : textDecorationLineString.split(" ")) {
if (token.equals("underline")) {
view.setPaintFlags(view.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
} else if (token.equals("line-through")) {
view.setPaintFlags(view.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
}
}

@ReactPropGroup(
names = {
ViewProps.BORDER_WIDTH,
Expand Down

0 comments on commit 536ee8b

Please sign in to comment.