diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java index 559f35848..6af26e8d7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java @@ -624,18 +624,24 @@ public class LayoutShadowNode extends ReactShadowNodeImpl { padding.recycle(); } - @ReactPropGroup(names = { + @ReactPropGroup( + names = { ViewProps.BORDER_WIDTH, - ViewProps.BORDER_LEFT_WIDTH, - ViewProps.BORDER_RIGHT_WIDTH, + ViewProps.BORDER_START_WIDTH, + ViewProps.BORDER_END_WIDTH, ViewProps.BORDER_TOP_WIDTH, ViewProps.BORDER_BOTTOM_WIDTH, - }, defaultFloat = YogaConstants.UNDEFINED) + ViewProps.BORDER_LEFT_WIDTH, + ViewProps.BORDER_RIGHT_WIDTH, + }, + defaultFloat = YogaConstants.UNDEFINED + ) public void setBorderWidths(int index, float borderWidth) { if (isVirtual()) { return; } - setBorder(ViewProps.BORDER_SPACING_TYPES[index], PixelUtil.toPixelFromDIP(borderWidth)); + int spacingType = maybeTransformLeftRightToStartEnd(ViewProps.BORDER_SPACING_TYPES[index]); + setBorder(spacingType, PixelUtil.toPixelFromDIP(borderWidth)); } @ReactPropGroup( diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 2ca7428e8..f3aa680c1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -103,6 +103,8 @@ public class ViewProps { public static final String BORDER_WIDTH = "borderWidth"; public static final String BORDER_LEFT_WIDTH = "borderLeftWidth"; + public static final String BORDER_START_WIDTH = "borderStartWidth"; + public static final String BORDER_END_WIDTH = "borderEndWidth"; public static final String BORDER_TOP_WIDTH = "borderTopWidth"; public static final String BORDER_RIGHT_WIDTH = "borderRightWidth"; public static final String BORDER_BOTTOM_WIDTH = "borderBottomWidth"; @@ -117,7 +119,13 @@ public class ViewProps { public static final String BORDER_TOP_COLOR = "borderTopColor"; public static final String BORDER_BOTTOM_COLOR = "borderBottomColor"; public static final int[] BORDER_SPACING_TYPES = { - Spacing.ALL, Spacing.START, Spacing.END, Spacing.TOP, Spacing.BOTTOM + Spacing.ALL, + Spacing.START, + Spacing.END, + Spacing.TOP, + Spacing.BOTTOM, + Spacing.LEFT, + Spacing.RIGHT }; public static final int[] PADDING_MARGIN_SPACING_TYPES = { Spacing.ALL, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK index 4e709c430..b5587be3d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK @@ -16,6 +16,7 @@ android_library( react_native_target("java/com/facebook/react/touch:touch"), react_native_target("java/com/facebook/react/views/common:common"), react_native_target("java/com/facebook/react/uimanager:uimanager"), + react_native_target("java/com/facebook/react/modules/i18nmanager:i18nmanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index d383ea6fc..d3b4ef209 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -9,6 +9,7 @@ package com.facebook.react.views.view; +import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -23,7 +24,9 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; import android.os.Build; +import android.view.View; import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.uimanager.FloatUtil; import com.facebook.react.uimanager.Spacing; import com.facebook.yoga.YogaConstants; @@ -105,6 +108,7 @@ public class ReactViewBackgroundDrawable extends Drawable { private int mAlpha = 255; private @Nullable float[] mBorderCornerRadii; + private final Context mContext; public enum BorderRadiusLocation { TOP_LEFT, @@ -113,6 +117,10 @@ public class ReactViewBackgroundDrawable extends Drawable { BOTTOM_LEFT } + public ReactViewBackgroundDrawable(Context context) { + mContext = context; + } + @Override public void draw(Canvas canvas) { updatePathEffect(); @@ -810,9 +818,14 @@ public class ReactViewBackgroundDrawable extends Drawable { mPaint.setStyle(Paint.Style.FILL); canvas.drawRect(getBounds(), mPaint); } + // maybe draw borders? - if (getBorderWidth(Spacing.LEFT) > 0 || getBorderWidth(Spacing.TOP) > 0 || - getBorderWidth(Spacing.RIGHT) > 0 || getBorderWidth(Spacing.BOTTOM) > 0) { + if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && (getBorderWidth(Spacing.START) > 0 || getBorderWidth(Spacing.END) > 0)) + || getBorderWidth(Spacing.LEFT) > 0 + || getBorderWidth(Spacing.TOP) > 0 + || getBorderWidth(Spacing.RIGHT) > 0 + || getBorderWidth(Spacing.BOTTOM) > 0) { Rect bounds = getBounds(); int borderLeft = getBorderWidth(Spacing.LEFT); @@ -824,6 +837,39 @@ public class ReactViewBackgroundDrawable extends Drawable { int colorRight = getBorderColor(Spacing.RIGHT); int colorBottom = getBorderColor(Spacing.BOTTOM); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + final boolean isRTL = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + int borderStart = getBorderWidth(Spacing.START); + int borderEnd = getBorderWidth(Spacing.END); + + if (I18nUtil.getInstance().doesRTLFlipLeftAndRightStyles(mContext)) { + if (borderStart < 0) { + borderStart = borderLeft; + } + + if (borderEnd < 0) { + borderEnd = borderRight; + } + + final int directionAwareBorderLeft = isRTL ? borderEnd : borderStart; + final int directionAwareBorderRight = isRTL ? borderStart : borderEnd; + + borderLeft = directionAwareBorderLeft; + borderRight = directionAwareBorderRight; + } else { + final int directionAwareBorderLeft = isRTL ? borderEnd : borderStart; + final int directionAwareBorderRight = isRTL ? borderStart : borderEnd; + + if (directionAwareBorderLeft >= 0) { + borderLeft = directionAwareBorderLeft; + } + + if (directionAwareBorderRight >= 0) { + borderRight = directionAwareBorderRight; + } + } + } + int left = bounds.left; int top = bounds.top; @@ -961,7 +1007,12 @@ public class ReactViewBackgroundDrawable extends Drawable { } private int getBorderWidth(int position) { - return mBorderWidth != null ? Math.round(mBorderWidth.get(position)) : 0; + if (mBorderWidth == null) { + return 0; + } + + final float width = mBorderWidth.get(position); + return YogaConstants.isUndefined(width) ? -1 : Math.round(width); } private static int colorFromAlphaAndRGBComponents(float alpha, float rgb) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java index daf12b202..0248b93c6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java @@ -21,7 +21,7 @@ public class ReactViewBackgroundManager { private ReactViewBackgroundDrawable getOrCreateReactViewBackground() { if (mReactBackgroundDrawable == null) { - mReactBackgroundDrawable = new ReactViewBackgroundDrawable(); + mReactBackgroundDrawable = new ReactViewBackgroundDrawable(mView.getContext()); Drawable backgroundDrawable = mView.getBackground(); ViewHelper.setBackground( mView, null); // required so that drawable callback is cleared before we add the diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 399a13e3f..448c39f9a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -24,6 +24,7 @@ import android.view.ViewGroup; import android.view.animation.Animation; import com.facebook.infer.annotation.Assertions; import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.touch.OnInterceptTouchEventListener; import com.facebook.react.touch.ReactHitSlopView; import com.facebook.react.touch.ReactInterceptingViewGroup; @@ -105,10 +106,10 @@ public class ReactViewGroup extends ViewGroup implements private boolean mNeedsOffscreenAlphaCompositing = false; private final ViewGroupDrawingOrderHelper mDrawingOrderHelper; private @Nullable Path mPath; + private int mLayoutDirection; public ReactViewGroup(Context context) { super(context); - mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); } @@ -126,6 +127,15 @@ public class ReactViewGroup extends ViewGroup implements // No-op since UIManagerModule handles actually laying out children. } + @Override + public void onRtlPropertiesChanged(int layoutDirection) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (mReactBackgroundDrawable != null) { + mReactBackgroundDrawable.setLayoutDirection(mLayoutDirection); + } + } + } + @Override public void requestLayout() { // No-op, terminate `requestLayout` here, UIManagerModule handles laying out children and @@ -565,7 +575,7 @@ public class ReactViewGroup extends ViewGroup implements private ReactViewBackgroundDrawable getOrCreateReactViewBackground() { if (mReactBackgroundDrawable == null) { - mReactBackgroundDrawable = new ReactViewBackgroundDrawable(); + mReactBackgroundDrawable = new ReactViewBackgroundDrawable(getContext()); Drawable backgroundDrawable = getBackground(); updateBackgroundDrawable( null); // required so that drawable callback is cleared before we add the @@ -577,6 +587,14 @@ public class ReactViewGroup extends ViewGroup implements new LayerDrawable(new Drawable[] {mReactBackgroundDrawable, backgroundDrawable}); updateBackgroundDrawable(layerDrawable); } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + mLayoutDirection = + I18nUtil.getInstance().isRTL(getContext()) + ? LAYOUT_DIRECTION_RTL + : LAYOUT_DIRECTION_LTR; + mReactBackgroundDrawable.setLayoutDirection(mLayoutDirection); + } } return mReactBackgroundDrawable; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 77104de53..e01046190 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -42,7 +42,13 @@ public class ReactViewManager extends ViewGroupManager { public static final String REACT_CLASS = ViewProps.VIEW_CLASS_NAME; private static final int[] SPACING_TYPES = { - Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM, + Spacing.ALL, + Spacing.LEFT, + Spacing.RIGHT, + Spacing.TOP, + Spacing.BOTTOM, + Spacing.START, + Spacing.END, }; private static final int CMD_HOTSPOT_UPDATE = 1; private static final int CMD_SET_PRESSED = 2; @@ -127,13 +133,18 @@ public class ReactViewManager extends ViewGroupManager { view.setNeedsOffscreenAlphaCompositing(needsOffscreenAlphaCompositing); } - @ReactPropGroup(names = { + @ReactPropGroup( + names = { ViewProps.BORDER_WIDTH, ViewProps.BORDER_LEFT_WIDTH, ViewProps.BORDER_RIGHT_WIDTH, ViewProps.BORDER_TOP_WIDTH, ViewProps.BORDER_BOTTOM_WIDTH, - }, defaultFloat = YogaConstants.UNDEFINED) + ViewProps.BORDER_START_WIDTH, + ViewProps.BORDER_END_WIDTH, + }, + defaultFloat = YogaConstants.UNDEFINED + ) public void setBorderWidth(ReactViewGroup view, int index, float width) { if (!YogaConstants.isUndefined(width)) { width = PixelUtil.toPixelFromDIP(width);