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 9e374b4c502ecb..1a31a0cc38bd37 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 @@ -90,9 +90,11 @@ private static enum BorderStyle { private @Nullable Path mOuterClipPathForBorderRadius; private @Nullable Path mPathForBorderRadiusOutline; private @Nullable Path mPathForBorder; + private @Nullable Path mCenterDrawPath; private @Nullable RectF mInnerClipTempRectForBorderRadius; private @Nullable RectF mOuterClipTempRectForBorderRadius; private @Nullable RectF mTempRectForBorderRadiusOutline; + private @Nullable RectF mTempRectForCenterDrawPath; private @Nullable PointF mInnerTopLeftCorner; private @Nullable PointF mInnerTopRightCorner; private @Nullable PointF mInnerBottomRightCorner; @@ -343,110 +345,130 @@ private void drawRoundedBackgroundWithBorders(Canvas canvas) { || borderWidth.bottom > 0 || borderWidth.left > 0 || borderWidth.right > 0) { - mPaint.setStyle(Paint.Style.FILL); - // Draw border - canvas.clipPath(mOuterClipPathForBorderRadius, Region.Op.INTERSECT); - canvas.clipPath(mInnerClipPathForBorderRadius, Region.Op.DIFFERENCE); + //If it's a full and even border draw inner rect path with stroke + final float fullBorderWidth = getFullBorderWidth(); + if (borderWidth.top == fullBorderWidth && + borderWidth.bottom == fullBorderWidth && + borderWidth.left == fullBorderWidth && + borderWidth.right == fullBorderWidth) { + if (fullBorderWidth > 0) { + int borderColor = getBorderColor(Spacing.ALL); + mPaint.setColor(ColorUtil.multiplyColorAlpha(borderColor, mAlpha)); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(fullBorderWidth); + canvas.drawPath(mCenterDrawPath, mPaint); + } + } + //In the case of uneven border widths/colors draw quadrilateral in each direction + else { + mPaint.setStyle(Paint.Style.FILL); - int colorLeft = getBorderColor(Spacing.LEFT); - int colorTop = getBorderColor(Spacing.TOP); - int colorRight = getBorderColor(Spacing.RIGHT); - int colorBottom = getBorderColor(Spacing.BOTTOM); + // Draw border + canvas.clipPath(mOuterClipPathForBorderRadius, Region.Op.INTERSECT); + canvas.clipPath(mInnerClipPathForBorderRadius, Region.Op.DIFFERENCE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - int colorStart = getBorderColor(Spacing.START); - int colorEnd = getBorderColor(Spacing.END); + int colorLeft = getBorderColor(Spacing.LEFT); + int colorTop = getBorderColor(Spacing.TOP); + int colorRight = getBorderColor(Spacing.RIGHT); + int colorBottom = getBorderColor(Spacing.BOTTOM); - if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { - if (!isBorderColorDefined(Spacing.START)) { - colorStart = colorLeft; - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + int colorStart = getBorderColor(Spacing.START); + int colorEnd = getBorderColor(Spacing.END); - if (!isBorderColorDefined(Spacing.END)) { - colorEnd = colorRight; - } + if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { + if (!isBorderColorDefined(Spacing.START)) { + colorStart = colorLeft; + } - final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; - final int directionAwareColorRight = isRTL ? colorStart : colorEnd; + if (!isBorderColorDefined(Spacing.END)) { + colorEnd = colorRight; + } - colorLeft = directionAwareColorLeft; - colorRight = directionAwareColorRight; - } else { - final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; - final int directionAwareColorRight = isRTL ? colorStart : colorEnd; + final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; + final int directionAwareColorRight = isRTL ? colorStart : colorEnd; - final boolean isColorStartDefined = isBorderColorDefined(Spacing.START); - final boolean isColorEndDefined = isBorderColorDefined(Spacing.END); - final boolean isDirectionAwareColorLeftDefined = isRTL ? isColorEndDefined : isColorStartDefined; - final boolean isDirectionAwareColorRightDefined = isRTL ? isColorStartDefined : isColorEndDefined; - - if (isDirectionAwareColorLeftDefined) { colorLeft = directionAwareColorLeft; - } - - if (isDirectionAwareColorRightDefined) { colorRight = directionAwareColorRight; + } else { + final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; + final int directionAwareColorRight = isRTL ? colorStart : colorEnd; + + final boolean isColorStartDefined = isBorderColorDefined(Spacing.START); + final boolean isColorEndDefined = isBorderColorDefined(Spacing.END); + final boolean isDirectionAwareColorLeftDefined = + isRTL ? isColorEndDefined : isColorStartDefined; + final boolean isDirectionAwareColorRightDefined = + isRTL ? isColorStartDefined : isColorEndDefined; + + if (isDirectionAwareColorLeftDefined) { + colorLeft = directionAwareColorLeft; + } + + if (isDirectionAwareColorRightDefined) { + colorRight = directionAwareColorRight; + } } } - } - final float left = mOuterClipTempRectForBorderRadius.left; - final float right = mOuterClipTempRectForBorderRadius.right; - final float top = mOuterClipTempRectForBorderRadius.top; - final float bottom = mOuterClipTempRectForBorderRadius.bottom; - - if (borderWidth.left > 0) { - final float x1 = left; - final float y1 = top; - final float x2 = mInnerTopLeftCorner.x; - final float y2 = mInnerTopLeftCorner.y; - final float x3 = mInnerBottomLeftCorner.x; - final float y3 = mInnerBottomLeftCorner.y; - final float x4 = left; - final float y4 = bottom; - - drawQuadrilateral(canvas, colorLeft, x1, y1, x2, y2, x3, y3, x4, y4); - } + final float left = mOuterClipTempRectForBorderRadius.left; + final float right = mOuterClipTempRectForBorderRadius.right; + final float top = mOuterClipTempRectForBorderRadius.top; + final float bottom = mOuterClipTempRectForBorderRadius.bottom; - if (borderWidth.top > 0) { - final float x1 = left; - final float y1 = top; - final float x2 = mInnerTopLeftCorner.x; - final float y2 = mInnerTopLeftCorner.y; - final float x3 = mInnerTopRightCorner.x; - final float y3 = mInnerTopRightCorner.y; - final float x4 = right; - final float y4 = top; - - drawQuadrilateral(canvas, colorTop, x1, y1, x2, y2, x3, y3, x4, y4); - } + if (borderWidth.left > 0) { + final float x1 = left; + final float y1 = top; + final float x2 = mInnerTopLeftCorner.x; + final float y2 = mInnerTopLeftCorner.y; + final float x3 = mInnerBottomLeftCorner.x; + final float y3 = mInnerBottomLeftCorner.y; + final float x4 = left; + final float y4 = bottom; - if (borderWidth.right > 0) { - final float x1 = right; - final float y1 = top; - final float x2 = mInnerTopRightCorner.x; - final float y2 = mInnerTopRightCorner.y; - final float x3 = mInnerBottomRightCorner.x; - final float y3 = mInnerBottomRightCorner.y; - final float x4 = right; - final float y4 = bottom; - - drawQuadrilateral(canvas, colorRight, x1, y1, x2, y2, x3, y3, x4, y4); - } + drawQuadrilateral(canvas, colorLeft, x1, y1, x2, y2, x3, y3, x4, y4); + } + + if (borderWidth.top > 0) { + final float x1 = left; + final float y1 = top; + final float x2 = mInnerTopLeftCorner.x; + final float y2 = mInnerTopLeftCorner.y; + final float x3 = mInnerTopRightCorner.x; + final float y3 = mInnerTopRightCorner.y; + final float x4 = right; + final float y4 = top; + + drawQuadrilateral(canvas, colorTop, x1, y1, x2, y2, x3, y3, x4, y4); + } + + if (borderWidth.right > 0) { + final float x1 = right; + final float y1 = top; + final float x2 = mInnerTopRightCorner.x; + final float y2 = mInnerTopRightCorner.y; + final float x3 = mInnerBottomRightCorner.x; + final float y3 = mInnerBottomRightCorner.y; + final float x4 = right; + final float y4 = bottom; - if (borderWidth.bottom > 0) { - final float x1 = left; - final float y1 = bottom; - final float x2 = mInnerBottomLeftCorner.x; - final float y2 = mInnerBottomLeftCorner.y; - final float x3 = mInnerBottomRightCorner.x; - final float y3 = mInnerBottomRightCorner.y; - final float x4 = right; - final float y4 = bottom; - - drawQuadrilateral(canvas, colorBottom, x1, y1, x2, y2, x3, y3, x4, y4); + drawQuadrilateral(canvas, colorRight, x1, y1, x2, y2, x3, y3, x4, y4); + } + + if (borderWidth.bottom > 0) { + final float x1 = left; + final float y1 = bottom; + final float x2 = mInnerBottomLeftCorner.x; + final float y2 = mInnerBottomLeftCorner.y; + final float x3 = mInnerBottomRightCorner.x; + final float y3 = mInnerBottomRightCorner.y; + final float x4 = right; + final float y4 = bottom; + + drawQuadrilateral(canvas, colorBottom, x1, y1, x2, y2, x3, y3, x4, y4); + } } } @@ -472,6 +494,10 @@ private void updatePath() { mPathForBorderRadiusOutline = new Path(); } + if (mCenterDrawPath == null) { + mCenterDrawPath = new Path(); + } + if (mInnerClipTempRectForBorderRadius == null) { mInnerClipTempRectForBorderRadius = new RectF(); } @@ -484,13 +510,24 @@ private void updatePath() { mTempRectForBorderRadiusOutline = new RectF(); } + if (mTempRectForCenterDrawPath == null) { + mTempRectForCenterDrawPath = new RectF(); + } + mInnerClipPathForBorderRadius.reset(); mOuterClipPathForBorderRadius.reset(); mPathForBorderRadiusOutline.reset(); + mCenterDrawPath.reset(); mInnerClipTempRectForBorderRadius.set(getBounds()); mOuterClipTempRectForBorderRadius.set(getBounds()); mTempRectForBorderRadiusOutline.set(getBounds()); + mTempRectForCenterDrawPath.set(getBounds()); + + float fullBorderWidth = getFullBorderWidth(); + if (fullBorderWidth > 0) { + mTempRectForCenterDrawPath.inset(fullBorderWidth * 0.5f, fullBorderWidth * 0.5f); + } final RectF borderWidth = getDirectionAwareBorderInsets(); @@ -623,6 +660,20 @@ private void updatePath() { }, Path.Direction.CW); + mCenterDrawPath.addRoundRect( + mTempRectForCenterDrawPath, + new float[] { + innerTopLeftRadiusX + extraRadiusForOutline, + innerTopLeftRadiusY + extraRadiusForOutline, + innerTopRightRadiusX + extraRadiusForOutline, + innerTopRightRadiusY + extraRadiusForOutline, + innerBottomRightRadiusX + extraRadiusForOutline, + innerBottomRightRadiusY + extraRadiusForOutline, + innerBottomLeftRadiusX + extraRadiusForOutline, + innerBottomLeftRadiusY + extraRadiusForOutline + }, + Path.Direction.CW); + /** * Rounded Multi-Colored Border Algorithm: *