Flip text alignment in case layout direction is RTL

Summary:
Changelog: [Internal]

Flip text alignment in case layout direction is RTL.

Reviewed By: JoshuaGross, mdvacca

Differential Revision: D21130371

fbshipit-source-id: cf56ca052c17a48e321803b0f99f8a4baaa0e67b
This commit is contained in:
Samuel Susla
2020-04-21 05:40:07 -07:00
committed by Facebook GitHub Bot
parent 05c76be176
commit a136b34c35
5 changed files with 36 additions and 7 deletions
@@ -97,6 +97,7 @@ public class ViewProps {
public static final String ON = "on";
public static final String RESIZE_MODE = "resizeMode";
public static final String RESIZE_METHOD = "resizeMethod";
public static final String LAYOUT_DIRECTION = "layoutDirection";
public static final String TEXT_ALIGN = "textAlign";
public static final String TEXT_ALIGN_VERTICAL = "textAlignVertical";
public static final String TEXT_DECORATION_LINE = "textDecorationLine";
@@ -87,7 +87,6 @@ public class ReactTextViewManager
ReadableNativeMap state = stateWrapper.getState();
ReadableMap attributedString = state.getMap("attributedString");
ReadableMap paragraphAttributes = state.getMap("paragraphAttributes");
Spannable spanned =
TextLayoutManager.getOrCreateSpannableForText(
view.getContext(), attributedString, mReactTextViewManagerCallback);
@@ -100,7 +99,7 @@ public class ReactTextViewManager
spanned,
state.hasKey("mostRecentEventCount") ? state.getInt("mostRecentEventCount") : -1,
false, // TODO add this into local Data
TextAttributeProps.getTextAlignment(props),
TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)),
textBreakStrategy,
TextAttributeProps.getJustificationMode(props));
}
@@ -10,6 +10,7 @@ package com.facebook.react.views.text;
import android.graphics.Typeface;
import android.os.Build;
import android.text.Layout;
import android.util.LayoutDirection;
import android.view.Gravity;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
@@ -57,6 +58,9 @@ public class TextAttributeProps {
protected float mLetterSpacingInput = Float.NaN;
protected int mTextAlign = Gravity.NO_GRAVITY;
// `UNSET` is -1 and is the same as `LayoutDirection.UNDEFINED` but the symbol isn't available.
protected int mLayoutDirection = UNSET;
protected TextTransform mTextTransform = TextTransform.UNSET;
protected float mTextShadowOffsetDx = 0;
@@ -129,10 +133,10 @@ public class TextAttributeProps {
setTextShadowRadius(getIntProp(PROP_SHADOW_RADIUS, 1));
setTextShadowColor(getIntProp(PROP_SHADOW_COLOR, DEFAULT_TEXT_SHADOW_COLOR));
setTextTransform(getStringProp(PROP_TEXT_TRANSFORM));
setLayoutDirection(getStringProp(ViewProps.LAYOUT_DIRECTION));
}
// TODO T63645393 add support for RTL
public static int getTextAlignment(ReactStylesDiffMap props) {
public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL) {
@Nullable
String textAlignPropValue =
props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null;
@@ -144,9 +148,9 @@ public class TextAttributeProps {
if (textAlignPropValue == null || "auto".equals(textAlignPropValue)) {
textAlignment = Gravity.NO_GRAVITY;
} else if ("left".equals(textAlignPropValue)) {
textAlignment = Gravity.LEFT;
textAlignment = isRTL ? Gravity.RIGHT : Gravity.LEFT;
} else if ("right".equals(textAlignPropValue)) {
textAlignment = Gravity.RIGHT;
textAlignment = isRTL ? Gravity.LEFT : Gravity.RIGHT;
} else if ("center".equals(textAlignPropValue)) {
textAlignment = Gravity.CENTER_HORIZONTAL;
} else {
@@ -369,6 +373,19 @@ public class TextAttributeProps {
}
}
public void setLayoutDirection(@Nullable String layoutDirection) {
if (layoutDirection == null || "undefined".equals(layoutDirection)) {
mLayoutDirection = UNSET;
} else if ("rtl".equals(layoutDirection)) {
mLayoutDirection = LayoutDirection.RTL;
} else if ("ltr".equals(layoutDirection)) {
mLayoutDirection = LayoutDirection.LTR;
} else {
throw new JSApplicationIllegalArgumentException(
"Invalid layoutDirection: " + layoutDirection);
}
}
public void setTextShadowRadius(float textShadowRadius) {
if (textShadowRadius != mTextShadowRadius) {
mTextShadowRadius = textShadowRadius;
@@ -18,6 +18,7 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.LayoutDirection;
import android.util.LruCache;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
@@ -47,6 +48,17 @@ public class TextLayoutManager {
private static final Object sSpannableCacheLock = new Object();
private static LruCache<String, Spannable> sSpannableCache = new LruCache<>(spannableCacheSize);
public static boolean isRTL(ReadableMap attributedString) {
ReadableArray fragments = attributedString.getArray("fragments");
for (int i = 0, length = fragments.size(); i < length; i++) {
ReadableMap fragment = fragments.getMap(i);
ReactStylesDiffMap map = new ReactStylesDiffMap(fragment.getMap("textAttributes"));
TextAttributeProps textAttributes = new TextAttributeProps(map);
return textAttributes.mLayoutDirection == LayoutDirection.RTL;
}
return false;
}
private static void buildSpannableFromFragment(
Context context,
ReadableArray fragments,
@@ -1285,7 +1285,7 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
spanned,
state.getInt("mostRecentEventCount"),
false, // TODO add this into local Data
TextAttributeProps.getTextAlignment(props),
TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)),
textBreakStrategy,
TextAttributeProps.getJustificationMode(props),
attributedString);