From eacbaa4317539070c1b50c0457eca4005c40120f Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 20 Mar 2023 19:29:16 -0700 Subject: [PATCH] Minimize EditText Spans 6/N: letterSpacing (#36548) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36548 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]( https://github.com/facebook/react-native/issues/35936#issuecomment-1411437789) for greater context on the platform behavior. This change lets us set `letterSpacing` on the EditText instead of using our custom span. Changelog: [Android][Fixed] - Minimize EditText Spans 6/N: letterSpacing Differential Revision: D44240777 fbshipit-source-id: d7defe4b18acd5faa61309f375e9e33945d7231d --- .../views/text/CustomLetterSpacingSpan.java | 4 ++++ .../react/views/textinput/ReactEditText.java | 23 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java index 3b9cf58e33d3a1..d537cd5dccc101 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java @@ -37,6 +37,10 @@ public void updateMeasureState(TextPaint paint) { apply(paint); } + public float getSpacing() { + return mLetterSpacing; + } + private void apply(TextPaint paint) { if (!Float.isNaN(mLetterSpacing)) { paint.setLetterSpacing(mLetterSpacing); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 4bb327cc3bfc50..c64476760a3fbd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -726,6 +726,18 @@ public boolean test(ReactUnderlineSpan span) { return (getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0; } }); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + stripSpansOfKind( + sb, + CustomLetterSpacingSpan.class, + new SpanPredicate() { + @Override + public boolean test(CustomLetterSpacingSpan span) { + return span.getSpacing() == mTextAttributes.getEffectiveLetterSpacing(); + } + }); + } } private void stripSpansOfKind( @@ -780,6 +792,13 @@ private void restoreStyleEquivalentSpans(SpannableStringBuilder workingText) { spans.add(new ReactUnderlineSpan()); } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing(); + if (!Float.isNaN(effectiveLetterSpacing)) { + spans.add(new CustomLetterSpacingSpan(effectiveLetterSpacing)); + } + } + for (Object span : spans) { workingText.setSpan(span, 0, workingText.length(), spanFlags); } @@ -1137,7 +1156,9 @@ protected void applyTextAttributes() { float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing(); if (!Float.isNaN(effectiveLetterSpacing)) { - setLetterSpacing(effectiveLetterSpacing); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setLetterSpacing(effectiveLetterSpacing); + } } }