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
This commit is contained in:
parent
ee89ffcb17
commit
54a4450309
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -55,24 +55,6 @@ public class ReactTextViewManager extends BaseViewManager<ReactTextView, ReactTe
|
|||
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 class ReactTextInputShadowNode extends ReactTextShadowNode implements
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue