8

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
  • 1,223
  • 4
  • 13
  • 26

6 Answers6

13

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.

Bruno Caceiro
  • 7,035
  • 1
  • 26
  • 45
  • 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 Sep 05 '19 at 11:38
  • Also, changing the CornerRadius via code in the constructor (like above) simply doesn't do anything. – Sander Koldenhof Sep 05 '19 at 11:46
  • Here I must add that I'm creating a new page (thus new PancakeView) for the second page. – Sander Koldenhof Sep 05 '19 at 11:47
10

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/

Cherry Bu - MSFT
  • 10,160
  • 1
  • 10
  • 16
  • 1
    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 Sep 05 '19 at 10:04
  • @Sander, I am not sure what you mean, can you provide screenshot? – Cherry Bu - MSFT Sep 06 '19 at 01:44
  • 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. – Sander Koldenhof Sep 06 '19 at 07:12
  • The solution did not work for iOS, it does go through the custom renderer, but on device there is no effect. – Edgaras Aug 07 '20 at 13:28
4

You can use BoxView instead of Frame

<Grid Margin="10,10,80,10">
    <BoxView Color="#CCE4FF"
             CornerRadius="10,10,10,0"
             HorizontalOptions="Fill"
             VerticalOptions="Fill" />
    <Grid Padding="10">
        <Label Text="This is my message"
           FontSize="14"
           TextColor="#434343"/>
    </Grid>
</Grid>

result view

Alex Soloh
  • 61
  • 3
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

David Jesus
  • 1,981
  • 2
  • 29
  • 34
2

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);
        }
    }
}
xiawi
  • 1,772
  • 4
  • 19
  • 21
Sven
  • 31
  • 11
1

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>