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

# Conflicts:
#	ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java
#	ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java
This commit is contained in:
Pieter De Baets
2023-04-17 12:39:12 +01:00
committed by Lorenzo Sciandra
parent 9be29593c8
commit 843d57ecc1
5 changed files with 52 additions and 34 deletions
@@ -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 class ReactTextView extends AppCompatTextView implements ReactCompoundVie
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 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
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 class ReactTextView extends AppCompatTextView implements ReactCompoundVie
}
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 class ReactTextView extends AppCompatTextView implements ReactCompoundVie
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;
@@ -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.ReactAccessibilityDelegate;
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 class ReactTextViewManager
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 @@ public class ReactTextViewManager
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
@@ -249,35 +249,35 @@ public class TextAttributeProps {
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 {
throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlignPropValue);
}
}
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;
}
@@ -911,6 +911,11 @@ public class ReactEditText extends AppCompatEditText
}
}
/* package */ int getGravityHorizontal() {
return getGravity()
& (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK);
}
/* package */ void setGravityHorizontal(int gravityHorizontal) {
if (gravityHorizontal == 0) {
gravityHorizontal = mDefaultGravityHorizontal;
@@ -1326,10 +1326,7 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
}
ReadableNativeMap state = stateWrapper.getStateData();
if (state == null) {
return null;
}
if (!state.hasKey("attributedString")) {
if (state == null || !state.hasKey("attributedString")) {
return null;
}
@@ -1344,12 +1341,16 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
view.getContext(), attributedString, mReactTextViewManagerCallback);
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, currentJustificationMode));
}
@@ -1375,12 +1376,14 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
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, currentJustificationMode));
}