Skip to content

Commit

Permalink
Change the textalign setter to support RTL
Browse files Browse the repository at this point in the history
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
MengjueW authored and Facebook Github Bot 6 committed Jul 26, 2016
1 parent ee89ffc commit 54a4450
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 28 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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);
}
}
Expand Down
Expand Up @@ -10,6 +10,7 @@
package com.facebook.react.views.text;

import android.text.Spannable;
import android.view.Gravity;

import com.facebook.csslayout.Spacing;

Expand All @@ -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;
Expand All @@ -43,6 +46,7 @@ public ReactTextUpdate(
mPaddingRight = padding.get(Spacing.RIGHT);
mPaddingBottom = padding.get(Spacing.BOTTOM);
mLineHeight = lineHeight;
mTextAlign = textAlign;
}

public Spannable getText() {
Expand Down Expand Up @@ -76,4 +80,8 @@ public float getPaddingBottom() {
public float getLineHeight() {
return mLineHeight;
}

public int getTextAlign() {
return mTextAlign;
}
}
Expand Up @@ -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);
Expand Down Expand Up @@ -62,6 +63,12 @@ public void setText(ReactTextUpdate update) {
setLineSpacing(mLineHeight, 0);
}
}

int nextTextAlign = update.getTextAlign();
if (mTextAlign != nextTextAlign) {
mTextAlign = nextTextAlign;
}
setGravityHorizontal(mTextAlign);
}

@Override
Expand Down
Expand Up @@ -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) {
Expand Down
Expand Up @@ -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);
}
}
Expand Down

0 comments on commit 54a4450

Please sign in to comment.