Xamarin Frame only have a single rounded corner

10,889

Solution 1

Another way it to use custom render for frame.

1.Create class name CustomFrame, inherit Frame class, add BindableProperty CornerRadiusProperty in PCL.

 public class CustomFrame: Frame
{
    public static new readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CustomFrame), typeof(CornerRadius), typeof(CustomFrame));
    public CustomFrame()
    {
        // MK Clearing default values (e.g. on iOS it's 5)
        base.CornerRadius = 0;
    }

    public new CornerRadius CornerRadius
    {
        get => (CornerRadius)GetValue(CornerRadiusProperty);
        set => SetValue(CornerRadiusProperty, value);
    }

}
  1. create CustomFrameRender in Android.

    using FrameRenderer = Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer;
    
    [assembly: ExportRenderer(typeof(CustomFrame), typeof(CustomFrameRenderer))]
    namespace Demo1.Droid
    {
    class CustomFrameRenderer : FrameRenderer
     {
    public CustomFrameRenderer(Context context)
        : base(context)
    {
    }
    
    protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);
    
        if (e.NewElement != null && Control != null)
        {
            UpdateCornerRadius();
        }
    }
    
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
    
        if (e.PropertyName == nameof(CustomFrame.CornerRadius) ||
            e.PropertyName == nameof(CustomFrame))
        {
            UpdateCornerRadius();
        }
    }
    
    private void UpdateCornerRadius()
    {
        if (Control.Background is GradientDrawable backgroundGradient)
        {
            var cornerRadius = (Element as CustomFrame)?.CornerRadius;
            if (!cornerRadius.HasValue)
            {
                return;
            }
    
            var topLeftCorner = Context.ToPixels(cornerRadius.Value.TopLeft);
            var topRightCorner = Context.ToPixels(cornerRadius.Value.TopRight);
            var bottomLeftCorner = Context.ToPixels(cornerRadius.Value.BottomLeft);
            var bottomRightCorner = Context.ToPixels(cornerRadius.Value.BottomRight);
    
            var cornerRadii = new[]
            {
                topLeftCorner,
                topLeftCorner,
    
                topRightCorner,
                topRightCorner,
    
                bottomRightCorner,
                bottomRightCorner,
    
                bottomLeftCorner,
                bottomLeftCorner,
            };
    
            backgroundGradient.SetCornerRadii(cornerRadii);
        }
    }
    
      }
     }
    

3.using custonframe in forms.

<StackLayout>
        <controls:CustomFrame
            BackgroundColor="Red"
            CornerRadius="0,30,0,0"
            HeightRequest="100"
            HorizontalOptions="Center"
            VerticalOptions="Center"
            WidthRequest="100" />
    </StackLayout>

More detailed info about this, please refer to:

https://progrunning.net/customizing-corner-radius/

Solution 2

The easy way is to use the Nuget PancakeView.

You can specify the CornerRadius in each vertice, achieving the desired effect:

Example:

<yummy:PancakeView BackgroundColor="Orange"CornerRadius="60,0,0,60"/>

You can read more in the official page.

Solution 3

Use the nuget package Xamarin.Forms.PancakeView. enter image description here

Look at this answer for a similar question:

https://stackoverflow.com/a/59650125/5869384

Solution 4

This is for UWP renderer

I've used the solutions from Cherry Bu - MSFT and changed it for UWP. In my project im using it in Android, iOS and UWP and it is working fine.

using System.ComponentModel;
using Windows.UI.Xaml.Media;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ExportRenderer(typeof(CustomFrame), typeof(yourNamespace.UWP.CustomFrameRenderer))]
namespace yourNamespace.UWP
{
    public class CustomFrameRenderer : FrameRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null && Control != null)
            {
                UpdateCornerRadius();
            }
        }

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

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

        private void UpdateCornerRadius()
        {
            var radius = ((CustomFrame)this.Element).CornerRadius;
            Control.CornerRadius = new Windows.UI.Xaml.CornerRadius(radius.TopLeft, radius.TopRight, radius.BottomRight, radius.BottomLeft);
        }
    }
}

Solution 5

simple solution i have used is to set another frame behind the rounded frame something like this

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.05*"/>
        <RowDefinition Height="0.05*"/>
        <RowDefinition Height="0.8*"/>
        <RowDefinition Height="0.05*"/>
        <RowDefinition Height="0.05*"/>
    </Grid.RowDefinitions>


    <Frame
        Grid.Row="4"
        Padding="0"
        BackgroundColor="Green"
        CornerRadius="0"/>
    
    <Frame
        Grid.Row="3"
        Grid.RowSpan="2"
        Padding="0"
        BackgroundColor="Green"
        HasShadow="True"
        CornerRadius="20">
    </Frame>

</Grid>
Share:
10,889
Sander Koldenhof
Author by

Sander Koldenhof

Updated on June 15, 2022

Comments

  • Sander Koldenhof
    Sander Koldenhof about 2 years

    Simple question. I need a frame with only one rounded corner, instead of all four. How can I only round one of the corners of a frame (top right in my case)?

    Another way to phrase it: How can I set the cornerradius of only one corner of a frame?

  • Sander Koldenhof
    Sander Koldenhof almost 5 years
    This works fairly well, but I ran into an issue. The content of the frame ignores the curved corners unlike usual (it draws the content outside the frame corner). Any idea how to fix this?
  • Sander Koldenhof
    Sander Koldenhof almost 5 years
    Hey there, I tested out PancakeVIew but the application crashes when I try to set the cornerradius via C# to something other than it's base value (I.E. frame.CornerRadius = new CornerRadius(10,10,0,0)), when going back via navigationpage. The main page has a long list of pancaceviews, and clicking on one of them brings you to a page with a single pancakeview. Going back to the mainscreen (using Navigation) breaks the application. Any idea how?
  • Sander Koldenhof
    Sander Koldenhof almost 5 years
    Also, changing the CornerRadius via code in the constructor (like above) simply doesn't do anything.
  • Sander Koldenhof
    Sander Koldenhof almost 5 years
    Here I must add that I'm creating a new page (thus new PancakeView) for the second page.
  • Cherry Bu - MSFT
    Cherry Bu - MSFT almost 5 years
    @Sander, I am not sure what you mean, can you provide screenshot?
  • Sander Koldenhof
    Sander Koldenhof almost 5 years
    I already swapped to PancakeView (which also has some problems I'm trying to figure out), but Basically this happens: When you add a frame, the edge of the frame is the limit of where stuff can be drawn. If you add a cornerradius, it also cuts away from the "canvas" the content can be drawn on, resulting in a round image for example. With this custom frame, it renders the corners (out), but does not edit this "canvas", so the content won't have the round corners, but overlaps the frame (as if the corner radius was set to 0). I hope that explains my issue well enough.
  • Edgaras
    Edgaras almost 4 years
    The solution did not work for iOS, it does go through the custom renderer, but on device there is no effect.