Permalink
Browse files

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
  • Loading branch information...
1 parent ee89ffc commit 54a4450309bfbbcd07e5e2ffe2a2cd1aaf772cc3 @MengjueW MengjueW committed with Facebook Github Bot 6 Jul 26, 2016
@@ -27,13 +27,16 @@
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 void measure(
/**
* 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 @@ private static int parseNumericFontWeight(String fontWeightString) {
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 float getEffectiveLineHeight() {
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 void setLineHeight(int lineHeight) {
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 void setBackgroundColor(Integer color) {
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 void setFontWeight(@Nullable String fontWeightString) {
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 void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
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);
}
}
@@ -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 @@
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 ReactTextUpdate(
mPaddingRight = padding.get(Spacing.RIGHT);
mPaddingBottom = padding.get(Spacing.BOTTOM);
mLineHeight = lineHeight;
+ mTextAlign = textAlign;
}
public Spannable getText() {
@@ -76,4 +80,8 @@ public float getPaddingBottom() {
public float getLineHeight() {
return mLineHeight;
}
+
+ public int getTextAlign() {
+ return mTextAlign;
+ }
}
@@ -30,6 +30,7 @@
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 void setText(ReactTextUpdate update) {
setLineSpacing(mLineHeight, 0);
}
}
+
+ int nextTextAlign = update.getTextAlign();
+ if (mTextAlign != nextTextAlign) {
+ mTextAlign = nextTextAlign;
+ }
+ setGravityHorizontal(mTextAlign);
}
@Override
@@ -55,24 +55,6 @@ public void setNumberOfLines(ReactTextView view, int numberOfLines) {
view.setEllipsize(TextUtils.TruncateAt.END);
}
- @ReactProp(name = ViewProps.TEXT_ALIGN)
- public void setTextAlign(ReactTextView view, @Nullable String textAlign) {
- if (textAlign == null || "auto".equals(textAlign)) {
- view.setGravityHorizontal(Gravity.NO_GRAVITY);
- } else if ("left".equals(textAlign)) {
- view.setGravityHorizontal(Gravity.LEFT);
- } else if ("right".equals(textAlign)) {
- view.setGravityHorizontal(Gravity.RIGHT);
- } else if ("center".equals(textAlign)) {
- view.setGravityHorizontal(Gravity.CENTER_HORIZONTAL);
- } else if ("justify".equals(textAlign)) {
- // Fallback gracefully for cross-platform compat instead of error
- view.setGravityHorizontal(Gravity.LEFT);
- } else {
- throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign);
- }
- }
-
@ReactProp(name = ViewProps.LINE_BREAK_MODE)
public void setLineBreakMode(ReactTextView view, @Nullable String ellipsizeMode) {
if(ellipsizeMode == null) {
@@ -119,7 +119,14 @@ public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
if (mJsEventCount != UNSET) {
Spannable preparedSpannableText = fromTextCSSNode(this);
ReactTextUpdate reactTextUpdate =
- new ReactTextUpdate(preparedSpannableText, mJsEventCount, mContainsImages, getPadding(), getEffectiveLineHeight());
+ new ReactTextUpdate(
+ preparedSpannableText,
+ mJsEventCount,
+ mContainsImages,
+ getPadding(),
+ getEffectiveLineHeight(),
+ mTextAlign
+ );
uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate);
}
}

0 comments on commit 54a4450

Please sign in to comment.