Android: Implement border(Start|End)Width for non-rounded borders
Reviewed By: achen1 Differential Revision: D5917755 fbshipit-source-id: 3ec0ab1a1e191f5f6fd956691995e95937a513cc
This commit is contained in:
parent
04a8c62313
commit
7ed7593b2b
|
@ -624,18 +624,24 @@ public class LayoutShadowNode extends ReactShadowNodeImpl {
|
||||||
padding.recycle();
|
padding.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactPropGroup(names = {
|
@ReactPropGroup(
|
||||||
|
names = {
|
||||||
ViewProps.BORDER_WIDTH,
|
ViewProps.BORDER_WIDTH,
|
||||||
ViewProps.BORDER_LEFT_WIDTH,
|
ViewProps.BORDER_START_WIDTH,
|
||||||
ViewProps.BORDER_RIGHT_WIDTH,
|
ViewProps.BORDER_END_WIDTH,
|
||||||
ViewProps.BORDER_TOP_WIDTH,
|
ViewProps.BORDER_TOP_WIDTH,
|
||||||
ViewProps.BORDER_BOTTOM_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) {
|
public void setBorderWidths(int index, float borderWidth) {
|
||||||
if (isVirtual()) {
|
if (isVirtual()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setBorder(ViewProps.BORDER_SPACING_TYPES[index], PixelUtil.toPixelFromDIP(borderWidth));
|
int spacingType = maybeTransformLeftRightToStartEnd(ViewProps.BORDER_SPACING_TYPES[index]);
|
||||||
|
setBorder(spacingType, PixelUtil.toPixelFromDIP(borderWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactPropGroup(
|
@ReactPropGroup(
|
||||||
|
|
|
@ -103,6 +103,8 @@ public class ViewProps {
|
||||||
|
|
||||||
public static final String BORDER_WIDTH = "borderWidth";
|
public static final String BORDER_WIDTH = "borderWidth";
|
||||||
public static final String BORDER_LEFT_WIDTH = "borderLeftWidth";
|
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_TOP_WIDTH = "borderTopWidth";
|
||||||
public static final String BORDER_RIGHT_WIDTH = "borderRightWidth";
|
public static final String BORDER_RIGHT_WIDTH = "borderRightWidth";
|
||||||
public static final String BORDER_BOTTOM_WIDTH = "borderBottomWidth";
|
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_TOP_COLOR = "borderTopColor";
|
||||||
public static final String BORDER_BOTTOM_COLOR = "borderBottomColor";
|
public static final String BORDER_BOTTOM_COLOR = "borderBottomColor";
|
||||||
public static final int[] BORDER_SPACING_TYPES = {
|
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 = {
|
public static final int[] PADDING_MARGIN_SPACING_TYPES = {
|
||||||
Spacing.ALL,
|
Spacing.ALL,
|
||||||
|
|
|
@ -16,6 +16,7 @@ android_library(
|
||||||
react_native_target("java/com/facebook/react/touch:touch"),
|
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/views/common:common"),
|
||||||
react_native_target("java/com/facebook/react/uimanager:uimanager"),
|
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"),
|
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
package com.facebook.react.views.view;
|
package com.facebook.react.views.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.ColorFilter;
|
import android.graphics.ColorFilter;
|
||||||
|
@ -23,7 +24,9 @@ import android.graphics.RectF;
|
||||||
import android.graphics.Region;
|
import android.graphics.Region;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
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.FloatUtil;
|
||||||
import com.facebook.react.uimanager.Spacing;
|
import com.facebook.react.uimanager.Spacing;
|
||||||
import com.facebook.yoga.YogaConstants;
|
import com.facebook.yoga.YogaConstants;
|
||||||
|
@ -105,6 +108,7 @@ public class ReactViewBackgroundDrawable extends Drawable {
|
||||||
private int mAlpha = 255;
|
private int mAlpha = 255;
|
||||||
|
|
||||||
private @Nullable float[] mBorderCornerRadii;
|
private @Nullable float[] mBorderCornerRadii;
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
public enum BorderRadiusLocation {
|
public enum BorderRadiusLocation {
|
||||||
TOP_LEFT,
|
TOP_LEFT,
|
||||||
|
@ -113,6 +117,10 @@ public class ReactViewBackgroundDrawable extends Drawable {
|
||||||
BOTTOM_LEFT
|
BOTTOM_LEFT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReactViewBackgroundDrawable(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
updatePathEffect();
|
updatePathEffect();
|
||||||
|
@ -810,9 +818,14 @@ public class ReactViewBackgroundDrawable extends Drawable {
|
||||||
mPaint.setStyle(Paint.Style.FILL);
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
canvas.drawRect(getBounds(), mPaint);
|
canvas.drawRect(getBounds(), mPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe draw borders?
|
// maybe draw borders?
|
||||||
if (getBorderWidth(Spacing.LEFT) > 0 || getBorderWidth(Spacing.TOP) > 0 ||
|
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||||
getBorderWidth(Spacing.RIGHT) > 0 || getBorderWidth(Spacing.BOTTOM) > 0) {
|
&& (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();
|
Rect bounds = getBounds();
|
||||||
|
|
||||||
int borderLeft = getBorderWidth(Spacing.LEFT);
|
int borderLeft = getBorderWidth(Spacing.LEFT);
|
||||||
|
@ -824,6 +837,39 @@ public class ReactViewBackgroundDrawable extends Drawable {
|
||||||
int colorRight = getBorderColor(Spacing.RIGHT);
|
int colorRight = getBorderColor(Spacing.RIGHT);
|
||||||
int colorBottom = getBorderColor(Spacing.BOTTOM);
|
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 left = bounds.left;
|
||||||
int top = bounds.top;
|
int top = bounds.top;
|
||||||
|
|
||||||
|
@ -961,7 +1007,12 @@ public class ReactViewBackgroundDrawable extends Drawable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getBorderWidth(int position) {
|
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) {
|
private static int colorFromAlphaAndRGBComponents(float alpha, float rgb) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class ReactViewBackgroundManager {
|
||||||
|
|
||||||
private ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
|
private ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
|
||||||
if (mReactBackgroundDrawable == null) {
|
if (mReactBackgroundDrawable == null) {
|
||||||
mReactBackgroundDrawable = new ReactViewBackgroundDrawable();
|
mReactBackgroundDrawable = new ReactViewBackgroundDrawable(mView.getContext());
|
||||||
Drawable backgroundDrawable = mView.getBackground();
|
Drawable backgroundDrawable = mView.getBackground();
|
||||||
ViewHelper.setBackground(
|
ViewHelper.setBackground(
|
||||||
mView, null); // required so that drawable callback is cleared before we add the
|
mView, null); // required so that drawable callback is cleared before we add the
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.view.ViewGroup;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import com.facebook.infer.annotation.Assertions;
|
import com.facebook.infer.annotation.Assertions;
|
||||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
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.OnInterceptTouchEventListener;
|
||||||
import com.facebook.react.touch.ReactHitSlopView;
|
import com.facebook.react.touch.ReactHitSlopView;
|
||||||
import com.facebook.react.touch.ReactInterceptingViewGroup;
|
import com.facebook.react.touch.ReactInterceptingViewGroup;
|
||||||
|
@ -105,10 +106,10 @@ public class ReactViewGroup extends ViewGroup implements
|
||||||
private boolean mNeedsOffscreenAlphaCompositing = false;
|
private boolean mNeedsOffscreenAlphaCompositing = false;
|
||||||
private final ViewGroupDrawingOrderHelper mDrawingOrderHelper;
|
private final ViewGroupDrawingOrderHelper mDrawingOrderHelper;
|
||||||
private @Nullable Path mPath;
|
private @Nullable Path mPath;
|
||||||
|
private int mLayoutDirection;
|
||||||
|
|
||||||
public ReactViewGroup(Context context) {
|
public ReactViewGroup(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this);
|
mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +127,15 @@ public class ReactViewGroup extends ViewGroup implements
|
||||||
// No-op since UIManagerModule handles actually laying out children.
|
// 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
|
@Override
|
||||||
public void requestLayout() {
|
public void requestLayout() {
|
||||||
// No-op, terminate `requestLayout` here, UIManagerModule handles laying out children and
|
// No-op, terminate `requestLayout` here, UIManagerModule handles laying out children and
|
||||||
|
@ -565,7 +575,7 @@ public class ReactViewGroup extends ViewGroup implements
|
||||||
|
|
||||||
private ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
|
private ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
|
||||||
if (mReactBackgroundDrawable == null) {
|
if (mReactBackgroundDrawable == null) {
|
||||||
mReactBackgroundDrawable = new ReactViewBackgroundDrawable();
|
mReactBackgroundDrawable = new ReactViewBackgroundDrawable(getContext());
|
||||||
Drawable backgroundDrawable = getBackground();
|
Drawable backgroundDrawable = getBackground();
|
||||||
updateBackgroundDrawable(
|
updateBackgroundDrawable(
|
||||||
null); // required so that drawable callback is cleared before we add the
|
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});
|
new LayerDrawable(new Drawable[] {mReactBackgroundDrawable, backgroundDrawable});
|
||||||
updateBackgroundDrawable(layerDrawable);
|
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;
|
return mReactBackgroundDrawable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,13 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
|
||||||
public static final String REACT_CLASS = ViewProps.VIEW_CLASS_NAME;
|
public static final String REACT_CLASS = ViewProps.VIEW_CLASS_NAME;
|
||||||
|
|
||||||
private static final int[] SPACING_TYPES = {
|
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_HOTSPOT_UPDATE = 1;
|
||||||
private static final int CMD_SET_PRESSED = 2;
|
private static final int CMD_SET_PRESSED = 2;
|
||||||
|
@ -127,13 +133,18 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
|
||||||
view.setNeedsOffscreenAlphaCompositing(needsOffscreenAlphaCompositing);
|
view.setNeedsOffscreenAlphaCompositing(needsOffscreenAlphaCompositing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactPropGroup(names = {
|
@ReactPropGroup(
|
||||||
|
names = {
|
||||||
ViewProps.BORDER_WIDTH,
|
ViewProps.BORDER_WIDTH,
|
||||||
ViewProps.BORDER_LEFT_WIDTH,
|
ViewProps.BORDER_LEFT_WIDTH,
|
||||||
ViewProps.BORDER_RIGHT_WIDTH,
|
ViewProps.BORDER_RIGHT_WIDTH,
|
||||||
ViewProps.BORDER_TOP_WIDTH,
|
ViewProps.BORDER_TOP_WIDTH,
|
||||||
ViewProps.BORDER_BOTTOM_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) {
|
public void setBorderWidth(ReactViewGroup view, int index, float width) {
|
||||||
if (!YogaConstants.isUndefined(width)) {
|
if (!YogaConstants.isUndefined(width)) {
|
||||||
width = PixelUtil.toPixelFromDIP(width);
|
width = PixelUtil.toPixelFromDIP(width);
|
||||||
|
|
Loading…
Reference in New Issue