0
votes

I have created a custom renderer for a frame to have rounded corners only on 2 sides. The code works fine in Android but in iOS the rounded corners are getting trimmed if the background color of frame is white and border color is blue like below image.

enter image description here

Custom Renderer IOS

public class CustomFrameRenderer : FrameRenderer
    {
        
        public override void LayoutSubviews()
        {
            base.LayoutSubviews();

            UpdateCornerRadius();
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == nameof(CustomFrame.CornerRadius) ||
                e.PropertyName == nameof(CustomFrame))
            {
                UpdateCornerRadius();
            }
        }

        // A very basic way of retrieving same one value for all of the corners
        private double RetrieveCommonCornerRadius(CornerRadius cornerRadius)
        {
            var commonCornerRadius = cornerRadius.TopLeft;
            if (commonCornerRadius <= 0)
            {
                commonCornerRadius = cornerRadius.TopRight;
                if (commonCornerRadius <= 0)
                {
                    commonCornerRadius = cornerRadius.BottomLeft;
                    if (commonCornerRadius <= 0)
                    {
                        commonCornerRadius = cornerRadius.BottomRight;
                    }
                }
            }

            return commonCornerRadius;
        }

        private UIRectCorner RetrieveRoundedCorners(CornerRadius cornerRadius)
        {
            var roundedCorners = default(UIRectCorner);

            if (cornerRadius.TopLeft > 0)
            {
                roundedCorners |= UIRectCorner.TopLeft;
            }

            if (cornerRadius.TopRight > 0)
            {
                roundedCorners |= UIRectCorner.TopRight;
            }

            if (cornerRadius.BottomLeft > 0)
            {
                roundedCorners |= UIRectCorner.BottomLeft;
            }

            if (cornerRadius.BottomRight > 0)
            {
                roundedCorners |= UIRectCorner.BottomRight;
            }

            return roundedCorners;
        }

        private void UpdateCornerRadius()
        {
            var cornerRadius = (Element as CustomFrame)?.CornerRadius;
            if (!cornerRadius.HasValue)
            {
                return;
            }

            var roundedCornerRadius = RetrieveCommonCornerRadius(cornerRadius.Value);
            if (roundedCornerRadius <= 0)
            {
                return;
            }

            var roundedCorners = RetrieveRoundedCorners(cornerRadius.Value);

            var path = UIBezierPath.FromRoundedRect(Bounds, roundedCorners, new CGSize(roundedCornerRadius, roundedCornerRadius));
            var mask = new CAShapeLayer { Path = path.CGPath };
            NativeView.Layer.Mask = mask;
            //NativeView.Layer.CornerRadius = 0;
            NativeView.ClipsToBounds = true;
            NativeView.Layer.MaskedCorners = (CoreAnimation.CACornerMask)3;

        }
    }

Can someone please help me to resolve below issue. Thanks.

2
Does it work now ?Lucas Zhang
No, I tried the below mentioned solution, it's not considering corner radius with thisMars
As it works fine on my side , could you share your sample so that I can test it on my side directly ?Lucas Zhang

2 Answers

0
votes

You could check the following code

  private void UpdateCornerRadius()
    {
        var cornerRadius = (Element as Frame)?.CornerRadius;
        if (!cornerRadius.HasValue)
        {
            return;
        }

        var roundedCornerRadius = RetrieveCommonCornerRadius(cornerRadius.Value);
        if (roundedCornerRadius <= 0)
        {
            return;
        }

        var roundedCorners = RetrieveRoundedCorners(cornerRadius.Value);

        NativeView.Layer.MasksToBounds = true;
        var path = UIBezierPath.FromRoundedRect(Bounds, roundedCorners, new CGSize(roundedCornerRadius, roundedCornerRadius));
        var mask = new CAShapeLayer { Path = path.CGPath };
        mask.Frame = Bounds;
        mask.LineWidth = 1;
        mask.StrokeColor = UIColor.SystemBlueColor.CGColor;  // border color
        mask.FillColor = UIColor.Clear.CGColor;  // bg color , you need to set it as clear otherwise it will cover its child element
        mask.ShadowRadius = 0;
      
        NativeView.Layer.AddSublayer(mask);
      
       // NativeView.Layer.MaskedCorners = (CoreAnimation.CACornerMask)3;
        
    }
-1
votes

A mask takes a layer, and trim that visual to match the mask.

So if a layer is a rectangle with black borders, and your mask is an oval,

an oval will appear with the color of the rectangle that it masks.

But it will not round those rectangle borders, just cut them out.

What you need to do instead is to build a layer that will replace NativeView.Layer

With your rounded rectangle, without using the mask.

Or change those values on the elements in the layer that already exist, directly.