diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index a66950c7966af6..d53f18a5aa3289 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -7,7 +7,6 @@ package com.facebook.react.views.text; -import android.annotation.TargetApi; import android.os.Build; import android.text.BoringLayout; import android.text.Layout; @@ -47,7 +46,6 @@ *

The class measures text in {@code } view and feeds native {@link TextView} using {@code * Spannable} object constructed in superclass. */ -@TargetApi(Build.VERSION_CODES.M) public class ReactTextShadowNode extends ReactBaseTextShadowNode { // It's important to pass the ANTI_ALIAS_FLAG flag to the constructor rather than setting it @@ -148,7 +146,7 @@ public long measure( } } - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { layoutWidth = (float) Math.ceil(layoutWidth); } float layoutHeight = height; @@ -222,28 +220,22 @@ private Layout measureSpannedText(Spannable text, float width, YogaMeasureMode w || (!YogaConstants.isUndefined(desiredWidth) && desiredWidth <= width))) { // Is used when the width is not known and the text is not boring, ie. if it contains // unicode characters. - int hintWidth = (int) Math.ceil(desiredWidth); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = - new StaticLayout(text, textPaint, hintWidth, alignment, 1.f, 0.f, mIncludeFontPadding); - } else { - StaticLayout.Builder builder = - StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, hintWidth) - .setAlignment(alignment) - .setLineSpacing(0.f, 1.f) - .setIncludePad(mIncludeFontPadding) - .setBreakStrategy(mTextBreakStrategy) - .setHyphenationFrequency(mHyphenationFrequency); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setJustificationMode(mJustificationMode); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - builder.setUseLineSpacingFromFallbacks(true); - } - layout = builder.build(); + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, hintWidth) + .setAlignment(alignment) + .setLineSpacing(0.f, 1.f) + .setIncludePad(mIncludeFontPadding) + .setBreakStrategy(mTextBreakStrategy) + .setHyphenationFrequency(mHyphenationFrequency); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + builder.setJustificationMode(mJustificationMode); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + builder.setUseLineSpacingFromFallbacks(true); } + layout = builder.build(); } else if (boring != null && (unconstrainedWidth || boring.width <= width)) { // Is used for single-line, boring text when the width is either unknown or bigger @@ -260,32 +252,25 @@ private Layout measureSpannedText(Spannable text, float width, YogaMeasureMode w mIncludeFontPadding); } else { // Is used for multiline, boring text and the width is known. + // Android 11+ introduces changes in text width calculation which leads to cases + // where the container is measured smaller than text. Math.ceil prevents it + // See T136756103 for investigation + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + width = (float) Math.ceil(width); + } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = - new StaticLayout( - text, textPaint, (int) width, alignment, 1.f, 0.f, mIncludeFontPadding); - } else { - // Android 11+ introduces changes in text width calculation which leads to cases - // where the container is measured smaller than text. Math.ceil prevents it - // See T136756103 for investigation - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.Q) { - width = (float) Math.ceil(width); - } - - StaticLayout.Builder builder = - StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, (int) width) - .setAlignment(alignment) - .setLineSpacing(0.f, 1.f) - .setIncludePad(mIncludeFontPadding) - .setBreakStrategy(mTextBreakStrategy) - .setHyphenationFrequency(mHyphenationFrequency); + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, (int) width) + .setAlignment(alignment) + .setLineSpacing(0.f, 1.f) + .setIncludePad(mIncludeFontPadding) + .setBreakStrategy(mTextBreakStrategy) + .setHyphenationFrequency(mHyphenationFrequency); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - builder.setUseLineSpacingFromFallbacks(true); - } - layout = builder.build(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + builder.setUseLineSpacingFromFallbacks(true); } + layout = builder.build(); } return layout; } @@ -361,6 +346,7 @@ public void setShouldNotifyOnTextLayout(boolean shouldNotifyOnTextLayout) { } @Override + @Nullable public Iterable calculateLayoutOnChildren() { // Run flexbox on and return the descendants which are inline views. @@ -374,7 +360,7 @@ public Iterable calculateLayoutOnChildren() { "Spannable element has not been prepared in onBeforeLayout"); TextInlineViewPlaceholderSpan[] placeholders = text.getSpans(0, text.length(), TextInlineViewPlaceholderSpan.class); - ArrayList shadowNodes = new ArrayList(placeholders.length); + ArrayList shadowNodes = new ArrayList<>(placeholders.length); for (TextInlineViewPlaceholderSpan placeholder : placeholders) { ReactShadowNode child = mInlineViews.get(placeholder.getReactTag()); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 4af57295d9aac6..83bacaafb9ea60 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -106,9 +106,7 @@ private void initView() { // Defaults for these fields: // https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/widget/TextView.java#L1061 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE); - } + setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE); setMovementMethod(getDefaultMovementMethod()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { setJustificationMode(Layout.JUSTIFICATION_MODE_NONE); @@ -145,10 +143,7 @@ private void initView() { setFocusable(View.FOCUSABLE_AUTO); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE); - } - + setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE); updateView(); // call after changing ellipsizeLocation in particular } @@ -399,10 +394,8 @@ public void setText(ReactTextUpdate update) { if (nextTextAlign != getGravityHorizontal()) { setGravityHorizontal(nextTextAlign); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (getBreakStrategy() != update.getTextBreakStrategy()) { - setBreakStrategy(update.getTextBreakStrategy()); - } + if (getBreakStrategy() != update.getTextBreakStrategy()) { + setBreakStrategy(update.getTextBreakStrategy()); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (getJustificationMode() != update.getJustificationMode()) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index eb03a50743f0d6..09bddc6ea292c5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -73,10 +73,8 @@ public class TextAttributeProps { private static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000; private static final int DEFAULT_JUSTIFICATION_MODE = (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) ? 0 : Layout.JUSTIFICATION_MODE_NONE; - private static final int DEFAULT_BREAK_STRATEGY = - (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.BREAK_STRATEGY_HIGH_QUALITY; - private static final int DEFAULT_HYPHENATION_FREQUENCY = - (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.HYPHENATION_FREQUENCY_NONE; + private static final int DEFAULT_BREAK_STRATEGY = Layout.BREAK_STRATEGY_HIGH_QUALITY; + private static final int DEFAULT_HYPHENATION_FREQUENCY = Layout.HYPHENATION_FREQUENCY_NONE; protected float mLineHeight = Float.NaN; protected boolean mIsColorSet = false; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index ffd5b2f1a5c4c2..93eda5d06b3866 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -258,26 +258,14 @@ private static Layout createLayout( // unicode characters. int hintWidth = (int) Math.ceil(desiredWidth); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = - new StaticLayout( - text, - sTextPaintInstance, - hintWidth, - Layout.Alignment.ALIGN_NORMAL, - 1.f, - 0.f, - includeFontPadding); - } else { - layout = - StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, hintWidth) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .setLineSpacing(0.f, 1.f) - .setIncludePad(includeFontPadding) - .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(hyphenationFrequency) - .build(); - } + layout = + StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, hintWidth) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLineSpacing(0.f, 1.f) + .setIncludePad(includeFontPadding) + .setBreakStrategy(textBreakStrategy) + .setHyphenationFrequency(hyphenationFrequency) + .build(); } else if (boring != null && (unconstrainedWidth || boring.width <= width)) { int boringLayoutWidth = boring.width; if (boring.width < 0) { @@ -300,32 +288,19 @@ private static Layout createLayout( includeFontPadding); } else { // Is used for multiline, boring text and the width is known. - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = - new StaticLayout( - text, - sTextPaintInstance, - (int) width, - Layout.Alignment.ALIGN_NORMAL, - 1.f, - 0.f, - includeFontPadding); - } else { - StaticLayout.Builder builder = - StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, (int) width) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .setLineSpacing(0.f, 1.f) - .setIncludePad(includeFontPadding) - .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(hyphenationFrequency); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - builder.setUseLineSpacingFromFallbacks(true); - } - - layout = builder.build(); + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, (int) width) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLineSpacing(0.f, 1.f) + .setIncludePad(includeFontPadding) + .setBreakStrategy(textBreakStrategy) + .setHyphenationFrequency(hyphenationFrequency); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + builder.setUseLineSpacingFromFallbacks(true); } + + layout = builder.build(); } return layout; } @@ -423,7 +398,7 @@ public static long measureText( // Android 11+ introduces changes in text width calculation which leads to cases // where the container is measured smaller than text. Math.ceil prevents it // See T136756103 for investigation - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { calculatedWidth = (float) Math.ceil(calculatedWidth); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index 8cd576494a1c24..60ef5f2e28de9d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -299,26 +299,14 @@ private static Layout createLayout( // unicode characters. int hintWidth = (int) Math.ceil(desiredWidth); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = - new StaticLayout( - text, - sTextPaintInstance, - hintWidth, - Layout.Alignment.ALIGN_NORMAL, - 1.f, - 0.f, - includeFontPadding); - } else { - layout = - StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, hintWidth) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .setLineSpacing(0.f, 1.f) - .setIncludePad(includeFontPadding) - .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(hyphenationFrequency) - .build(); - } + layout = + StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, hintWidth) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLineSpacing(0.f, 1.f) + .setIncludePad(includeFontPadding) + .setBreakStrategy(textBreakStrategy) + .setHyphenationFrequency(hyphenationFrequency) + .build(); } else if (boring != null && (unconstrainedWidth || boring.width <= width)) { int boringLayoutWidth = boring.width; @@ -341,32 +329,19 @@ private static Layout createLayout( includeFontPadding); } else { // Is used for multiline, boring text and the width is known. - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - layout = - new StaticLayout( - text, - sTextPaintInstance, - (int) width, - Layout.Alignment.ALIGN_NORMAL, - 1.f, - 0.f, - includeFontPadding); - } else { - StaticLayout.Builder builder = - StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, (int) width) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .setLineSpacing(0.f, 1.f) - .setIncludePad(includeFontPadding) - .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(hyphenationFrequency); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - builder.setUseLineSpacingFromFallbacks(true); - } - - layout = builder.build(); + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(text, 0, spanLength, sTextPaintInstance, (int) width) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLineSpacing(0.f, 1.f) + .setIncludePad(includeFontPadding) + .setBreakStrategy(textBreakStrategy) + .setHyphenationFrequency(hyphenationFrequency); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + builder.setUseLineSpacingFromFallbacks(true); } + + layout = builder.build(); } return layout; } @@ -445,7 +420,7 @@ public static long measureText( // Android 11+ introduces changes in text width calculation which leads to cases // where the container is measured smaller than text. Math.ceil prevents it // See T136756103 for investigation - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.Q) { + if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { calculatedWidth = (float) Math.ceil(calculatedWidth); } 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 081f2b80160f2c..ecc6165f7244bf 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 @@ -9,8 +9,6 @@ import static com.facebook.react.uimanager.UIManagerHelper.getReactContext; -import android.content.ClipData; -import android.content.ClipboardManager; import android.content.Context; import android.graphics.Color; import android.graphics.Paint; @@ -210,9 +208,7 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) { public void onDestroyActionMode(ActionMode mode) {} }; setCustomSelectionActionModeCallback(customActionModeCallback); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - setCustomInsertionActionModeCallback(customActionModeCallback); - } + setCustomInsertionActionModeCallback(customActionModeCallback); } @Override @@ -308,26 +304,7 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) { @Override public boolean onTextContextMenuItem(int id) { if (id == android.R.id.paste) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - id = android.R.id.pasteAsPlainText; - } else { - ClipboardManager clipboard = - (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); - ClipData previousClipData = clipboard.getPrimaryClip(); - if (previousClipData != null) { - for (int i = 0; i < previousClipData.getItemCount(); i++) { - final CharSequence text = previousClipData.getItemAt(i).coerceToText(getContext()); - final CharSequence paste = (text instanceof Spanned) ? text.toString() : text; - if (paste != null) { - ClipData clipData = ClipData.newPlainText(null, text); - clipboard.setPrimaryClip(clipData); - } - } - boolean actionPerformed = super.onTextContextMenuItem(id); - clipboard.setPrimaryClip(previousClipData); - return actionPerformed; - } - } + id = android.R.id.pasteAsPlainText; } return super.onTextContextMenuItem(id); } @@ -702,10 +679,8 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { } mDisableTextDiffing = false; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (getBreakStrategy() != reactTextUpdate.getTextBreakStrategy()) { - setBreakStrategy(reactTextUpdate.getTextBreakStrategy()); - } + if (getBreakStrategy() != reactTextUpdate.getTextBreakStrategy()) { + setBreakStrategy(reactTextUpdate.getTextBreakStrategy()); } // Update cached spans (in Fabric only).