Support RTL for Nodes
Summary: Nodes supports RTL now, just like non-Nodes does. Differential Revision: D3727028
This commit is contained in:
parent
d785390a35
commit
1f6642b34a
|
@ -15,10 +15,12 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.facebook.csslayout.CSSDirection;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.UIImplementation;
|
||||
|
@ -82,6 +84,7 @@ public class FlatUIImplementation extends UIImplementation {
|
|||
private final MoveProxy mMoveProxy = new MoveProxy();
|
||||
private final StateBuilder mStateBuilder;
|
||||
private @Nullable ReactImageManager mReactImageManager;
|
||||
private final ReactApplicationContext mReactContext;
|
||||
|
||||
private FlatUIImplementation(
|
||||
ReactApplicationContext reactContext,
|
||||
|
@ -89,6 +92,7 @@ public class FlatUIImplementation extends UIImplementation {
|
|||
ViewManagerRegistry viewManagers,
|
||||
FlatUIViewOperationQueue operationsQueue) {
|
||||
super(reactContext, viewManagers, operationsQueue);
|
||||
mReactContext = reactContext;
|
||||
mStateBuilder = new StateBuilder(operationsQueue);
|
||||
mReactImageManager = reactImageManager;
|
||||
}
|
||||
|
@ -105,7 +109,12 @@ public class FlatUIImplementation extends UIImplementation {
|
|||
mReactImageManager = null;
|
||||
}
|
||||
|
||||
return new FlatRootShadowNode();
|
||||
ReactShadowNode node = new FlatRootShadowNode();
|
||||
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
|
||||
if (sharedI18nUtilInstance.isRTL(mReactContext)) {
|
||||
node.setDirection(CSSDirection.RTL);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -201,14 +201,14 @@ import com.facebook.react.views.view.ReactClippingViewGroup;
|
|||
|
||||
@Override
|
||||
public int reactTagForTouch(float touchX, float touchY) {
|
||||
/**
|
||||
/*
|
||||
* Make sure we don't find any children if the pointer events are set to BOX_ONLY.
|
||||
* There is no need to special-case any other modes, because if PointerEvents are set to:
|
||||
* a) PointerEvents.AUTO - all children are included, nothing to exclude
|
||||
* b) PointerEvents.NONE - this method will NOT be executed, because the View will be filtered
|
||||
* out by TouchTargetHelper.
|
||||
* c) PointerEvents.BOX_NONE - TouchTargetHelper will make sure that {@link #reactTagForTouch()}
|
||||
* doesn't return getId().
|
||||
* doesn't return getId().
|
||||
*/
|
||||
SoftAssertions.assertCondition(
|
||||
mPointerEvents != PointerEvents.NONE,
|
||||
|
@ -1011,11 +1011,12 @@ import com.facebook.react.views.view.ReactClippingViewGroup;
|
|||
right = Math.max(right, child.getRight());
|
||||
bottom = Math.max(bottom, child.getBottom());
|
||||
}
|
||||
for (int i = 0; i < mDrawCommands.length; i++) {
|
||||
if (!(mDrawCommands[i] instanceof AbstractDrawCommand)) {
|
||||
|
||||
for (DrawCommand mDrawCommand : mDrawCommands) {
|
||||
if (!(mDrawCommand instanceof AbstractDrawCommand)) {
|
||||
continue;
|
||||
}
|
||||
AbstractDrawCommand drawCommand = (AbstractDrawCommand) mDrawCommands[i];
|
||||
AbstractDrawCommand drawCommand = (AbstractDrawCommand) mDrawCommand;
|
||||
left = Math.min(left, Math.round(drawCommand.getLeft()));
|
||||
top = Math.min(top, Math.round(drawCommand.getTop()));
|
||||
right = Math.max(right, Math.round(drawCommand.getRight()));
|
||||
|
@ -1180,7 +1181,7 @@ import com.facebook.react.views.view.ReactClippingViewGroup;
|
|||
return mHitSlopRect;
|
||||
}
|
||||
|
||||
public void setHitSlopRect(@Nullable Rect rect) {
|
||||
/* package */ void setHitSlopRect(@Nullable Rect rect) {
|
||||
mHitSlopRect = rect;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@ import javax.annotation.Nullable;
|
|||
import android.support.v4.text.TextDirectionHeuristicsCompat;
|
||||
import android.text.Layout;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
|
||||
import com.facebook.csslayout.CSSDirection;
|
||||
import com.facebook.csslayout.CSSMeasureMode;
|
||||
import com.facebook.csslayout.CSSNodeAPI;
|
||||
import com.facebook.csslayout.MeasureOutput;
|
||||
|
@ -49,7 +51,7 @@ import com.facebook.textcachewarmer.DefaultTextLayoutCacheWarmer;
|
|||
private float mSpacingMult = 1.0f;
|
||||
private float mSpacingAdd = 0.0f;
|
||||
private int mNumberOfLines = Integer.MAX_VALUE;
|
||||
private Layout.Alignment mAlignment = Layout.Alignment.ALIGN_NORMAL;
|
||||
private int mAlignment = Gravity.NO_GRAVITY;
|
||||
|
||||
public RCTText() {
|
||||
setMeasureFunction(this);
|
||||
|
@ -98,7 +100,7 @@ import com.facebook.textcachewarmer.DefaultTextLayoutCacheWarmer;
|
|||
mSpacingAdd,
|
||||
mSpacingMult,
|
||||
getFontStyle(),
|
||||
mAlignment);
|
||||
getAlignment());
|
||||
|
||||
if (mDrawCommand != null && !mDrawCommand.isFrozen()) {
|
||||
mDrawCommand.setLayout(layout);
|
||||
|
@ -163,7 +165,7 @@ import com.facebook.textcachewarmer.DefaultTextLayoutCacheWarmer;
|
|||
mSpacingAdd,
|
||||
mSpacingMult,
|
||||
getFontStyle(),
|
||||
mAlignment));
|
||||
getAlignment()));
|
||||
updateNodeRegion = true;
|
||||
}
|
||||
|
||||
|
@ -259,21 +261,40 @@ import com.facebook.textcachewarmer.DefaultTextLayoutCacheWarmer;
|
|||
@ReactProp(name = ViewProps.TEXT_ALIGN)
|
||||
public void setTextAlign(@Nullable String textAlign) {
|
||||
if (textAlign == null || "auto".equals(textAlign)) {
|
||||
mAlignment = Layout.Alignment.ALIGN_NORMAL;
|
||||
mAlignment = Gravity.NO_GRAVITY;
|
||||
} else if ("left".equals(textAlign)) {
|
||||
// left and right may yield potentially different results (relative to non-nodes) in cases
|
||||
// when supportsRTL="true" in the manifest.
|
||||
mAlignment = Layout.Alignment.ALIGN_NORMAL;
|
||||
mAlignment = Gravity.LEFT;
|
||||
} else if ("right".equals(textAlign)) {
|
||||
mAlignment = Layout.Alignment.ALIGN_OPPOSITE;
|
||||
mAlignment = Gravity.RIGHT;
|
||||
} else if ("center".equals(textAlign)) {
|
||||
mAlignment = Layout.Alignment.ALIGN_CENTER;
|
||||
mAlignment = Gravity.CENTER;
|
||||
} else {
|
||||
throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign);
|
||||
}
|
||||
|
||||
notifyChanged(false);
|
||||
}
|
||||
|
||||
public Layout.Alignment getAlignment() {
|
||||
boolean isRtl = getLayoutDirection() == CSSDirection.RTL;
|
||||
switch (mAlignment) {
|
||||
// Layout.Alignment.RIGHT and Layout.Alignment.LEFT are @hide :(
|
||||
case Gravity.LEFT:
|
||||
int index = isRtl ? /* RIGHT */ 4 : /* LEFT */ 3;
|
||||
return Layout.Alignment.values()[index];
|
||||
case Gravity.RIGHT:
|
||||
index = isRtl ? /* LEFT */ 3 : /* RIGHT */ 4;
|
||||
return Layout.Alignment.values()[index];
|
||||
case Gravity.CENTER:
|
||||
return Layout.Alignment.ALIGN_CENTER;
|
||||
case Gravity.NO_GRAVITY:
|
||||
default:
|
||||
return Layout.Alignment.ALIGN_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
private static Layout createTextLayout(
|
||||
int width,
|
||||
CSSMeasureMode widthMode,
|
||||
|
|
|
@ -11,11 +11,14 @@ package com.facebook.react.flat;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.facebook.csslayout.CSSDirection;
|
||||
import com.facebook.csslayout.CSSMeasureMode;
|
||||
import com.facebook.csslayout.CSSNodeAPI;
|
||||
import com.facebook.csslayout.MeasureOutput;
|
||||
|
@ -53,6 +56,7 @@ public class RCTTextInput extends RCTVirtualText implements AndroidView, CSSNode
|
|||
markUpdated();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@Override
|
||||
public void setThemedContext(ThemedReactContext themedContext) {
|
||||
super.setThemedContext(themedContext);
|
||||
|
@ -65,9 +69,9 @@ public class RCTTextInput extends RCTVirtualText implements AndroidView, CSSNode
|
|||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
setDefaultPadding(Spacing.LEFT, mEditText.getPaddingLeft());
|
||||
setDefaultPadding(Spacing.START, mEditText.getPaddingStart());
|
||||
setDefaultPadding(Spacing.TOP, mEditText.getPaddingTop());
|
||||
setDefaultPadding(Spacing.RIGHT, mEditText.getPaddingRight());
|
||||
setDefaultPadding(Spacing.END, mEditText.getPaddingEnd());
|
||||
setDefaultPadding(Spacing.BOTTOM, mEditText.getPaddingBottom());
|
||||
}
|
||||
|
||||
|
@ -89,9 +93,9 @@ public class RCTTextInput extends RCTVirtualText implements AndroidView, CSSNode
|
|||
(int) Math.ceil(PixelUtil.toPixelFromSP(ViewDefaults.FONT_SIZE_SP)) : fontSize);
|
||||
Spacing padding = getPadding();
|
||||
editText.setPadding(
|
||||
(int) Math.ceil(padding.get(Spacing.LEFT)),
|
||||
(int) Math.ceil(padding.get(Spacing.START)),
|
||||
(int) Math.ceil(padding.get(Spacing.TOP)),
|
||||
(int) Math.ceil(padding.get(Spacing.RIGHT)),
|
||||
(int) Math.ceil(padding.get(Spacing.END)),
|
||||
(int) Math.ceil(padding.get(Spacing.BOTTOM)));
|
||||
|
||||
if (mNumberOfLines != UNSET) {
|
||||
|
|
Loading…
Reference in New Issue