From 3d882b0999ca25cbab104700eb483bc5d5d9a1ab Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 30 Apr 2022 20:59:09 +0300 Subject: [PATCH] fix(ios): apply proper border radius to box shadow and view sublayers (#9881) --- packages/core/ui/styling/background.ios.ts | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/core/ui/styling/background.ios.ts b/packages/core/ui/styling/background.ios.ts index e3eb08627..034bfecbc 100644 --- a/packages/core/ui/styling/background.ios.ts +++ b/packages/core/ui/styling/background.ios.ts @@ -712,6 +712,7 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeScriptUIView, backgroun // TODO: use sublayer if its applied to a layout function drawBoxShadow(nativeView: NativeScriptUIView, view: View, boxShadow: CSSShadow, background: BackgroundDefinition, useSubLayer: boolean = false) { const layer: CALayer = iOSNativeHelper.getShadowLayer(nativeView, 'ns-box-shadow'); + const renderSize = view.getActualSize() || { width: 0, height: 0 }; layer.masksToBounds = false; nativeView.clipsToBounds = false; @@ -720,10 +721,23 @@ function drawBoxShadow(nativeView: NativeScriptUIView, view: View, boxShadow: CS // nativeView.clipsToBounds doesn't work view.setProperty('clipToBounds', false); + // This should match the view's border radius (only uniform radius is supported for now) + let cornerRadius = layout.toDeviceIndependentPixels(background.borderTopLeftRadius); + cornerRadius = Math.min(Math.min(renderSize.width / 2, renderSize.height / 2), cornerRadius); + + // Apply corner radius to sub layers as clipToBounds and masksToBounds are now set to false + const sublayers = nativeView.layer?.sublayers; + if (sublayers) { + for (let i = 0; i < sublayers.count; i++) { + sublayers.objectAtIndex(i).cornerRadius = cornerRadius; + } + } + if (!background.color?.a) { // add white background if view has a transparent background layer.backgroundColor = UIColor.whiteColor.CGColor; } + // shadow opacity is handled on the shadow's color instance layer.shadowOpacity = boxShadow.color?.a ? boxShadow.color?.a / 255 : 1; layer.shadowRadius = Length.toDevicePixels(boxShadow.blurRadius, 0.0); @@ -735,9 +749,6 @@ function drawBoxShadow(nativeView: NativeScriptUIView, view: View, boxShadow: CS Length.toDevicePixels(boxShadow.offsetY, 0.0) ); - // this should match the view's border radius - const cornerRadius = Length.toDevicePixels(view.style.borderRadius, 0.0); - // apply spreadRadius by expanding shadow layer bounds // prettier-ignore const bounds = CGRectInset(nativeView.bounds, @@ -751,10 +762,18 @@ function drawBoxShadow(nativeView: NativeScriptUIView, view: View, boxShadow: CS function clearBoxShadow(nativeView: NativeScriptUIView) { nativeView.clipsToBounds = true; + const sublayers = nativeView.layer?.sublayers; + if (sublayers) { + for (let i = 0; i < sublayers.count; i++) { + sublayers.objectAtIndex(i).cornerRadius = 0.0; + } + } + const layer: CALayer = iOSNativeHelper.getShadowLayer(nativeView, 'ns-box-shadow', false); if (!layer) { return; } + layer.masksToBounds = true; layer.shadowOffset = CGSizeMake(0, 0); layer.shadowColor = UIColor.clearColor.CGColor;