mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix issue where inset border radius was off when there is a border (#45658)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45658 The border radius of the inner "clear region" for inset shadows is based off of the border radius of the padding box path (i.e. the shadow path). Notably, this is not the View's given border radius iff there is a border present. To get this "inner border radius" I added a new method inside of `CSSBackgroundDrawable`. This logic was already present [here](https://www.internalfb.com/code/fbsource/[33e35cbf387a]/xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java?lines=643-650), so I tried to share most of the code there. There may be a better way to do this, but this seems to be the quickest. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D60083309 fbshipit-source-id: ace1ffa15fc3c0c09d4df096b604c9a2c91382c8
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a694e4b325
commit
8fe3ae3ccc
+16
-8
@@ -309,6 +309,12 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
return mBorderRadius;
|
||||
}
|
||||
|
||||
// Here, "inner" refers to the border radius on the inside of the border. So
|
||||
// it ends up being the "outer" border radius inset by the respective width.
|
||||
public float getInnerBorderRadius(float computedRadius, float borderWidth) {
|
||||
return Math.max(computedRadius - borderWidth, 0);
|
||||
}
|
||||
|
||||
public ComputedBorderRadius getComputedBorderRadius() {
|
||||
return mComputedBorderRadius;
|
||||
}
|
||||
@@ -640,14 +646,16 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
float bottomLeftRadius = mComputedBorderRadius.getBottomLeft();
|
||||
float bottomRightRadius = mComputedBorderRadius.getBottomRight();
|
||||
|
||||
final float innerTopLeftRadiusX = Math.max(topLeftRadius - borderWidth.left, 0);
|
||||
final float innerTopLeftRadiusY = Math.max(topLeftRadius - borderWidth.top, 0);
|
||||
final float innerTopRightRadiusX = Math.max(topRightRadius - borderWidth.right, 0);
|
||||
final float innerTopRightRadiusY = Math.max(topRightRadius - borderWidth.top, 0);
|
||||
final float innerBottomRightRadiusX = Math.max(bottomRightRadius - borderWidth.right, 0);
|
||||
final float innerBottomRightRadiusY = Math.max(bottomRightRadius - borderWidth.bottom, 0);
|
||||
final float innerBottomLeftRadiusX = Math.max(bottomLeftRadius - borderWidth.left, 0);
|
||||
final float innerBottomLeftRadiusY = Math.max(bottomLeftRadius - borderWidth.bottom, 0);
|
||||
final float innerTopLeftRadiusX = getInnerBorderRadius(topLeftRadius, borderWidth.left);
|
||||
final float innerTopLeftRadiusY = getInnerBorderRadius(topLeftRadius, borderWidth.top);
|
||||
final float innerTopRightRadiusX = getInnerBorderRadius(topRightRadius, borderWidth.right);
|
||||
final float innerTopRightRadiusY = getInnerBorderRadius(topRightRadius, borderWidth.top);
|
||||
final float innerBottomRightRadiusX =
|
||||
getInnerBorderRadius(bottomRightRadius, borderWidth.right);
|
||||
final float innerBottomRightRadiusY =
|
||||
getInnerBorderRadius(bottomRightRadius, borderWidth.bottom);
|
||||
final float innerBottomLeftRadiusX = getInnerBorderRadius(bottomLeftRadius, borderWidth.left);
|
||||
final float innerBottomLeftRadiusY = getInnerBorderRadius(bottomLeftRadius, borderWidth.bottom);
|
||||
|
||||
mInnerClipPathForBorderRadius.addRoundRect(
|
||||
mInnerClipTempRectForBorderRadius,
|
||||
|
||||
+52
-6
@@ -18,7 +18,11 @@ import androidx.annotation.RequiresApi
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.uimanager.FilterHelper
|
||||
import com.facebook.react.uimanager.LengthPercentage
|
||||
import com.facebook.react.uimanager.LengthPercentageType
|
||||
import com.facebook.react.uimanager.PixelUtil
|
||||
import com.facebook.react.uimanager.style.BorderRadiusProp
|
||||
import com.facebook.react.uimanager.style.BorderRadiusStyle
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
private const val TAG = "InsetBoxShadowDrawable"
|
||||
@@ -76,13 +80,10 @@ internal class InsetBoxShadowDrawable(
|
||||
clearRegionBounds.inset(spreadExtent, spreadExtent)
|
||||
clearRegionBounds.offset(
|
||||
PixelUtil.toPixelFromDIP(offsetX).roundToInt() + padding / 2,
|
||||
PixelUtil.toPixelFromDIP(offsetY).roundToInt() + padding / 2)
|
||||
PixelUtil.toPixelFromDIP(offsetY).roundToInt() + padding / 2,
|
||||
)
|
||||
val clearRegionBorderRadii =
|
||||
getShadowBorderRadii(
|
||||
-spreadExtent.toFloat(),
|
||||
background.borderRadius,
|
||||
clearRegionBounds.width().toFloat(),
|
||||
clearRegionBounds.height().toFloat())
|
||||
getClearRegionBorderRadii(spreadExtent, background, clearRegionBounds)
|
||||
|
||||
if (shadowPaint.colorFilter != colorFilter ||
|
||||
clearRegionDrawable.layoutDirection != layoutDirection ||
|
||||
@@ -129,4 +130,49 @@ internal class InsetBoxShadowDrawable(
|
||||
canvas.restore()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getClearRegionBorderRadii(
|
||||
spread: Int,
|
||||
background: CSSBackgroundDrawable,
|
||||
clearRegionBounds: Rect,
|
||||
): BorderRadiusStyle {
|
||||
val computedBorderRadii = background.computedBorderRadius
|
||||
val borderWidth = background.getDirectionAwareBorderInsets()
|
||||
|
||||
val topLeftRadius = computedBorderRadii.topLeft
|
||||
val topRightRadius = computedBorderRadii.topRight
|
||||
val bottomLeftRadius = computedBorderRadii.bottomLeft
|
||||
val bottomRightRadius = computedBorderRadii.bottomRight
|
||||
|
||||
val innerTopLeftRadius = background.getInnerBorderRadius(topLeftRadius, borderWidth.left)
|
||||
val innerTopRightRadius = background.getInnerBorderRadius(topRightRadius, borderWidth.right)
|
||||
val innerBottomRightRadius =
|
||||
background.getInnerBorderRadius(bottomRightRadius, borderWidth.right)
|
||||
val innerBottomLeftRadius = background.getInnerBorderRadius(bottomLeftRadius, borderWidth.left)
|
||||
|
||||
val innerBorderRadii = BorderRadiusStyle()
|
||||
innerBorderRadii.set(
|
||||
BorderRadiusProp.BORDER_TOP_LEFT_RADIUS,
|
||||
LengthPercentage(innerTopLeftRadius, LengthPercentageType.POINT),
|
||||
)
|
||||
innerBorderRadii.set(
|
||||
BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS,
|
||||
LengthPercentage(innerTopRightRadius, LengthPercentageType.POINT),
|
||||
)
|
||||
innerBorderRadii.set(
|
||||
BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS,
|
||||
LengthPercentage(innerBottomRightRadius, LengthPercentageType.POINT),
|
||||
)
|
||||
innerBorderRadii.set(
|
||||
BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS,
|
||||
LengthPercentage(innerBottomLeftRadius, LengthPercentageType.POINT),
|
||||
)
|
||||
|
||||
return getShadowBorderRadii(
|
||||
-spread.toFloat(),
|
||||
innerBorderRadii,
|
||||
clearRegionBounds.width().toFloat(),
|
||||
clearRegionBounds.height().toFloat(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user