From 31a8e92caddcdbef9fe74de53e7f412a7e998591 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 22 Feb 2023 03:17:24 -0800 Subject: [PATCH] Fix TextView alignment being reset on state updates Summary: Changelog: [Android][Fixed] Resolved bug with Text components in new arch losing text alignment state. Reviewed By: mdvacca Differential Revision: D34108943 fbshipit-source-id: 3992e9406345be919b5e3595fc1f9e61cf67a699 --- .../react/views/text/ReactTextView.java | 16 ++++++---- .../views/text/ReactTextViewManager.java | 18 ++++++++--- .../react/views/text/TextAttributeProps.java | 32 +++++++++---------- .../react/views/textinput/ReactEditText.java | 5 +++ .../textinput/ReactTextInputManager.java | 21 ++++++------ 5 files changed, 55 insertions(+), 37 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index e5e405682f005c..6e742793eafe49 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -54,7 +54,6 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie private boolean mContainsImages; private final int mDefaultGravityHorizontal; private final int mDefaultGravityVertical; - private int mTextAlign; private int mNumberOfLines; private TextUtils.TruncateAt mEllipsizeLocation; private boolean mAdjustsFontSizeToFit; @@ -69,8 +68,7 @@ public ReactTextView(Context context) { super(context); // Get these defaults only during the constructor - these should never be set otherwise - mDefaultGravityHorizontal = - getGravity() & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + mDefaultGravityHorizontal = getGravityHorizontal(); mDefaultGravityVertical = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; initView(); @@ -89,10 +87,10 @@ private void initView() { mReactBackgroundManager = new ReactViewBackgroundManager(this); - mTextAlign = Gravity.NO_GRAVITY; mNumberOfLines = ViewDefaults.NUMBER_OF_LINES; mAdjustsFontSizeToFit = false; mLinkifyMaskType = 0; + mNotifyOnInlineViewLayout = false; mTextIsSelectable = false; mEllipsizeLocation = TextUtils.TruncateAt.END; @@ -392,10 +390,9 @@ public void setText(ReactTextUpdate update) { } int nextTextAlign = update.getTextAlign(); - if (mTextAlign != nextTextAlign) { - mTextAlign = nextTextAlign; + if (nextTextAlign != getGravityHorizontal()) { + setGravityHorizontal(nextTextAlign); } - setGravityHorizontal(mTextAlign); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (getBreakStrategy() != update.getTextBreakStrategy()) { setBreakStrategy(update.getTextBreakStrategy()); @@ -552,6 +549,11 @@ public boolean hasOverlappingRendering() { return false; } + /* package */ int getGravityHorizontal() { + return getGravity() + & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + } + /* package */ void setGravityHorizontal(int gravityHorizontal) { if (gravityHorizontal == 0) { gravityHorizontal = mDefaultGravityHorizontal; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index 0c8a7f0621b9ea..705223f832d4c8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -8,6 +8,7 @@ package com.facebook.react.views.text; import android.content.Context; +import android.os.Build; import android.text.Spannable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -23,6 +24,7 @@ import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaMeasureMode; import java.util.HashMap; import java.util.Map; @@ -148,15 +150,19 @@ public Object updateState( view.setSpanned(spanned); int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return new ReactTextUpdate( spanned, state.hasKey("mostRecentEventCount") ? state.getInt("mostRecentEventCount") : -1, false, // TODO add this into local Data - TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), + TextAttributeProps.getTextAlignment( + props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props)); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } private Object getReactTextUpdate(ReactTextView view, ReactStylesDiffMap props, MapBuffer state) { @@ -171,15 +177,17 @@ private Object getReactTextUpdate(ReactTextView view, ReactStylesDiffMap props, int textBreakStrategy = TextAttributeProps.getTextBreakStrategy( paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return new ReactTextUpdate( spanned, -1, // UNUSED FOR TEXT false, // TODO add this into local Data TextAttributeProps.getTextAlignment( - props, TextLayoutManagerMapBuffer.isRTL(attributedString)), + props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props)); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 822969ad8d8fc9..d503a641808853 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -250,36 +250,36 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) { return result; } - public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL) { - @Nullable - String textAlignPropValue = - props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null; - int textAlignment; + public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL, int defaultValue) { + if (!props.hasKey(ViewProps.TEXT_ALIGN)) { + return defaultValue; + } + String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN); if ("justify".equals(textAlignPropValue)) { - textAlignment = Gravity.LEFT; + return Gravity.LEFT; } else { if (textAlignPropValue == null || "auto".equals(textAlignPropValue)) { - textAlignment = Gravity.NO_GRAVITY; + return Gravity.NO_GRAVITY; } else if ("left".equals(textAlignPropValue)) { - textAlignment = isRTL ? Gravity.RIGHT : Gravity.LEFT; + return isRTL ? Gravity.RIGHT : Gravity.LEFT; } else if ("right".equals(textAlignPropValue)) { - textAlignment = isRTL ? Gravity.LEFT : Gravity.RIGHT; + return isRTL ? Gravity.LEFT : Gravity.RIGHT; } else if ("center".equals(textAlignPropValue)) { - textAlignment = Gravity.CENTER_HORIZONTAL; + return Gravity.CENTER_HORIZONTAL; } else { FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlignPropValue); - textAlignment = Gravity.NO_GRAVITY; + return Gravity.NO_GRAVITY; } } - return textAlignment; } - public static int getJustificationMode(ReactStylesDiffMap props) { - @Nullable - String textAlignPropValue = - props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null; + public static int getJustificationMode(ReactStylesDiffMap props, int defaultValue) { + if (!props.hasKey(ViewProps.TEXT_ALIGN)) { + return defaultValue; + } + String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN); if ("justify".equals(textAlignPropValue) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return Layout.JUSTIFICATION_MODE_INTER_WORD; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 3bcff03e5f4be4..6e2e24cc29eaa1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -845,6 +845,11 @@ private void setIntrinsicContentSize() { } } + /* package */ int getGravityHorizontal() { + return getGravity() + & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + } + /* package */ void setGravityHorizontal(int gravityHorizontal) { if (gravityHorizontal == 0) { gravityHorizontal = mDefaultGravityHorizontal; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index ddbc072e20d38b..7059ca3ed48846 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -1315,10 +1315,7 @@ public Object updateState( } ReadableNativeMap state = stateWrapper.getStateData(); - if (state == null) { - return null; - } - if (!state.hasKey("attributedString")) { + if (state == null || !state.hasKey("attributedString")) { return null; } @@ -1336,14 +1333,18 @@ public Object updateState( attributedString.getArray("fragments").toArrayList().size() > 1; int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return ReactTextUpdate.buildReactTextUpdateFromState( spanned, state.getInt("mostRecentEventCount"), - TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), + TextAttributeProps.getTextAlignment( + props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props), + TextAttributeProps.getJustificationMode(props, currentJustificationMode), containsMultipleFragments); } @@ -1371,14 +1372,16 @@ public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, M int textBreakStrategy = TextAttributeProps.getTextBreakStrategy( paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return ReactTextUpdate.buildReactTextUpdateFromState( spanned, state.getInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT), TextAttributeProps.getTextAlignment( - props, TextLayoutManagerMapBuffer.isRTL(attributedString)), + props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props), + TextAttributeProps.getJustificationMode(props, currentJustificationMode), containsMultipleFragments); } }