From 54a4450309bfbbcd07e5e2ffe2a2cd1aaf772cc3 Mon Sep 17 00:00:00 2001 From: Mengjue Wang Date: Tue, 26 Jul 2016 12:09:29 -0700 Subject: [PATCH] Change the textalign setter to support RTL Summary: Change the textalign setter to support RTL. In order to support text alignment according to layout style, move the textalign setter bridge function from ReactTextViewManager.java to ReactTextShadowNode.java and calculate it correctly on RCTTextUpdate. Reviewed By: dmmiller Differential Revision: D3597494 fbshipit-source-id: e5ca17b99b4233cc49a447a34175473e339ff53d --- .../react/views/text/ReactTextShadowNode.java | 59 ++++++++++++++++--- .../react/views/text/ReactTextUpdate.java | 10 +++- .../react/views/text/ReactTextView.java | 7 +++ .../views/text/ReactTextViewManager.java | 18 ------ .../textinput/ReactTextInputShadowNode.java | 9 ++- 5 files changed, 75 insertions(+), 28 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index 5178281a1..2b9908132 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -27,13 +27,16 @@ import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.text.style.StrikethroughSpan; import android.text.style.UnderlineSpan; +import android.view.Gravity; import android.widget.TextView; +import com.facebook.csslayout.CSSDirection; import com.facebook.csslayout.CSSConstants; import com.facebook.csslayout.CSSMeasureMode; import com.facebook.csslayout.CSSNode; import com.facebook.csslayout.MeasureOutput; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.uimanager.IllegalViewOperationException; @@ -288,8 +291,8 @@ public class ReactTextShadowNode extends LayoutShadowNode { /** * Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise * return the weight. - * - * This code is duplicated in ReactTextInputManager + * + * This code is duplicated in ReactTextInputManager * TODO: Factor into a common place they can both use */ private static int parseNumericFontWeight(String fontWeightString) { @@ -307,6 +310,7 @@ public class ReactTextShadowNode extends LayoutShadowNode { protected int mNumberOfLines = UNSET; protected int mFontSize = UNSET; + protected int mTextAlign = UNSET; private float mTextShadowOffsetDx = 0; private float mTextShadowOffsetDy = 0; @@ -364,6 +368,19 @@ public class ReactTextShadowNode extends LayoutShadowNode { return useInlineViewHeight ? mHeightOfTallestInlineImage : mLineHeight; } + // Return text alignment according to LTR or RTL style + private int getTextAlign() { + int textAlign = mTextAlign; + if (getLayoutDirection() == CSSDirection.RTL) { + if (textAlign == Gravity.RIGHT) { + textAlign = Gravity.LEFT; + } else if (textAlign == Gravity.LEFT) { + textAlign = Gravity.RIGHT; + } + } + return textAlign; + } + @Override public void onBeforeLayout() { if (mIsVirtual) { @@ -400,6 +417,25 @@ public class ReactTextShadowNode extends LayoutShadowNode { markUpdated(); } + @ReactProp(name = ViewProps.TEXT_ALIGN) + public void setTextAlign(@Nullable String textAlign) { + if (textAlign == null || "auto".equals(textAlign)) { + mTextAlign = Gravity.NO_GRAVITY; + } else if ("left".equals(textAlign)) { + mTextAlign = Gravity.LEFT; + } else if ("right".equals(textAlign)) { + mTextAlign = Gravity.RIGHT; + } else if ("center".equals(textAlign)) { + mTextAlign = Gravity.CENTER_HORIZONTAL; + } else if ("justify".equals(textAlign)) { + // Fallback gracefully for cross-platform compat instead of error + mTextAlign = Gravity.LEFT; + } else { + throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign); + } + markUpdated(); + } + @ReactProp(name = ViewProps.FONT_SIZE, defaultFloat = UNSET) public void setFontSize(float fontSize) { if (fontSize != UNSET) { @@ -429,15 +465,15 @@ public class ReactTextShadowNode extends LayoutShadowNode { markUpdated(); } } - + @ReactProp(name = ViewProps.FONT_FAMILY) public void setFontFamily(@Nullable String fontFamily) { mFontFamily = fontFamily; markUpdated(); } - + /** - /* This code is duplicated in ReactTextInputManager + /* This code is duplicated in ReactTextInputManager /* TODO: Factor into a common place they can both use */ @ReactProp(name = ViewProps.FONT_WEIGHT) @@ -456,9 +492,9 @@ public class ReactTextShadowNode extends LayoutShadowNode { markUpdated(); } } - + /** - /* This code is duplicated in ReactTextInputManager + /* This code is duplicated in ReactTextInputManager /* TODO: Factor into a common place they can both use */ @ReactProp(name = ViewProps.FONT_STYLE) @@ -546,7 +582,14 @@ public class ReactTextShadowNode extends LayoutShadowNode { super.onCollectExtraUpdates(uiViewOperationQueue); if (mPreparedSpannableText != null) { ReactTextUpdate reactTextUpdate = - new ReactTextUpdate(mPreparedSpannableText, UNSET, mContainsImages, getPadding(), getEffectiveLineHeight()); + new ReactTextUpdate( + mPreparedSpannableText, + UNSET, + mContainsImages, + getPadding(), + getEffectiveLineHeight(), + getTextAlign() + ); uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java index 5acb167c5..410f3ef54 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java @@ -10,6 +10,7 @@ package com.facebook.react.views.text; import android.text.Spannable; +import android.view.Gravity; import com.facebook.csslayout.Spacing; @@ -28,13 +29,15 @@ public class ReactTextUpdate { private final float mPaddingRight; private final float mPaddingBottom; private final float mLineHeight; + private final int mTextAlign; public ReactTextUpdate( Spannable text, int jsEventCounter, boolean containsImages, Spacing padding, - float lineHeight) { + float lineHeight, + int textAlign) { mText = text; mJsEventCounter = jsEventCounter; mContainsImages = containsImages; @@ -43,6 +46,7 @@ public class ReactTextUpdate { mPaddingRight = padding.get(Spacing.RIGHT); mPaddingBottom = padding.get(Spacing.BOTTOM); mLineHeight = lineHeight; + mTextAlign = textAlign; } public Spannable getText() { @@ -76,4 +80,8 @@ public class ReactTextUpdate { public float getLineHeight() { return mLineHeight; } + + public int getTextAlign() { + return mTextAlign; + } } 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 9ef3df91a..819db6c69 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 @@ -30,6 +30,7 @@ public class ReactTextView extends TextView implements ReactCompoundView { private int mDefaultGravityVertical; private boolean mTextIsSelectable; private float mLineHeight = Float.NaN; + private int mTextAlign = Gravity.NO_GRAVITY; public ReactTextView(Context context) { super(context); @@ -62,6 +63,12 @@ public class ReactTextView extends TextView implements ReactCompoundView { setLineSpacing(mLineHeight, 0); } } + + int nextTextAlign = update.getTextAlign(); + if (mTextAlign != nextTextAlign) { + mTextAlign = nextTextAlign; + } + setGravityHorizontal(mTextAlign); } @Override 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 7d2ed43e7..6f0aa7253 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 @@ -55,24 +55,6 @@ public class ReactTextViewManager extends BaseViewManager