Hot to set each corner radius for the Frame? It can be set all by one, but I to set each of them individually, 2 rounded 2 normal.
4 Answers
You need to create a custom renderer on each platform. I don't know if you can control the radius individually but you can control whether the corner adheres to the radius or not.
Firstly, you need a custom class in your shared project that will act as your custom control ...
using System;
using Xamarin.Forms;
namespace MyApp.Controls
{
public class CustomFrame : Frame
{
// ---------------------------------------------------------------------------------------------------------------
public static readonly BindableProperty CornerRadiusTopLeftProperty = BindableProperty.Create(
propertyName: "CornerRadiusTopLeft",
returnType: typeof(bool),
declaringType: typeof(CustomFrame),
defaultValue: true,
defaultBindingMode: BindingMode.TwoWay
);
public bool CornerRadiusTopLeft
{
get { return (bool)GetValue(CornerRadiusTopLeftProperty); }
set { base.SetValue(CornerRadiusTopLeftProperty, value); }
}
// ---------------------------------------------------------------------------------------------------------------
public static readonly BindableProperty CornerRadiusTopRightProperty = BindableProperty.Create(
propertyName: "CornerRadiusTopRight",
returnType: typeof(bool),
declaringType: typeof(CustomFrame),
defaultValue: true,
defaultBindingMode: BindingMode.TwoWay
);
public bool CornerRadiusTopRight
{
get { return (bool)GetValue(CornerRadiusTopRightProperty); }
set { base.SetValue(CornerRadiusTopRightProperty, value); }
}
// ---------------------------------------------------------------------------------------------------------------
public static readonly BindableProperty CornerRadiusBottomLeftProperty = BindableProperty.Create(
propertyName: "CornerRadiusBottomLeft",
returnType: typeof(bool),
declaringType: typeof(CustomFrame),
defaultValue: true,
defaultBindingMode: BindingMode.TwoWay
);
public bool CornerRadiusBottomLeft
{
get { return (bool)GetValue(CornerRadiusBottomLeftProperty); }
set { base.SetValue(CornerRadiusBottomLeftProperty, value); }
}
// ---------------------------------------------------------------------------------------------------------------
public static readonly BindableProperty CornerRadiusBottomRightProperty = BindableProperty.Create(
propertyName: "CornerRadiusBottomRight",
returnType: typeof(bool),
declaringType: typeof(CustomFrame),
defaultValue: true,
defaultBindingMode: BindingMode.TwoWay
);
public bool CornerRadiusBottomRight
{
get { return (bool)GetValue(CornerRadiusBottomRightProperty); }
set { base.SetValue(CornerRadiusBottomRightProperty, value); }
}
}
}
You then need to create the renderer on each platform. I haven't done the Android side yet but this is what you need for iOS ...
using System;
using CoreAnimation;
using MyApp.iOS.CustomRenderers;
using Foundation;
using MyApp.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CustomFrame), typeof(CustomFrameRenderer))]
namespace MyApp.iOS.CustomRenderers
{
public class CustomFrameRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (Element != null)
{
var element = Element as CustomFrame;
int result = 0;
if (element.CornerRadiusTopLeft)
result += (int)CACornerMask.MinXMinYCorner;
if (element.CornerRadiusTopRight)
result += (int)CACornerMask.MaxXMinYCorner;
if (element.CornerRadiusBottomLeft)
result += (int)CACornerMask.MinXMaxYCorner;
if (element.CornerRadiusBottomRight)
result += (int)CACornerMask.MaxXMaxYCorner;
Layer.MaskedCorners = (CACornerMask)result;
};
}
}
}
You're then able to make use of it in your XAML file as a custom control.
Add the namespace to your page ...
xmlns:customControls="clr-namespace:MyApp.Controls"
... then add your custom frame ...
<customControls:CustomFrame BackgroundColor="White" CornerRadius="10" HasShadow="false"
CornerRadiusBottomLeft="false" CornerRadiusBottomRight="false" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Padding="15">
<!-- Add your other elements here -->
</customControls:CustomFrame>
I hope that helps you. Good luck with the Android renderer, I'm sure it's not hard, just haven't gotten to it yet.
No hacks, there is a very simple solution:
Use the nuget package Xamarin.Forms.PancakeView.
How to use it?
- Install the nuget package Xamarin.Forms.PancakeView.
- Then you need to do is tell our XAML page where it can find the PancakeView, which is done by adding the following attribute to our ContentPage:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView">
...
</ContentPage>
- Just smack a PancakeView onto that page and you're all set:
<yummy:PancakeView BackgroundColor="#bc91d7" CornerRadius="60,0,0,60" IsClippedToBounds="true" HorizontalOptions="FillAndExpand" HeightRequest="150">
<Image Source="unicorn.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Aspect="AspectFill" />
</yummy:PancakeView>
A very hacky attempt with xaml, and you can still notice artifacts on the borders, but for a quick go-go why not..
<Grid>
<Frame Margin="0,0,0,20" HasShadow="False" BorderColor="Transparent" CornerRadius="12" HorizontalOptions="Fill" VerticalOptions="Fill" BackgroundColor="Gray"/>
<Frame Margin="1,1,1,20" HasShadow="False" BorderColor="Transparent" CornerRadius="11" HorizontalOptions="Fill" VerticalOptions="Fill" BackgroundColor="White"/>
<Frame Margin="0,20,0,0" VerticalOptions="Fill" HasShadow="False" BorderColor="Transparent" CornerRadius="2" HorizontalOptions="Fill" BackgroundColor="Gray" />
<Frame Margin="1,20,1,1" VerticalOptions="Fill" HasShadow="False" BorderColor="Transparent" CornerRadius="2" HorizontalOptions="Fill" BackgroundColor="White" />
<BoxView Margin="1.75,15,1.75,15" HorizontalOptions="Fill" VerticalOptions="Fill" BackgroundColor="White" HeightRequest="19" StyleId="hide background"/>
<ContentView Margin="8" x:Name="MainContainer">
<StackLayout >
<Label TextColor="DimGray" Text="This is your main container"/>
<Label TextColor="DimGray" Text="Put stuff here"/>
</StackLayout>
</ContentView>
</Grid>
using Xamarin.Forms.PancakeView.
<yummy:PancakeView BackgroundColor="#2DA6EA" WidthRequest="300" HorizontalOptions="Start" CornerRadius="0,30,0,30">
<StackLayout>
<Label TextColor="White" Margin="10,0,0,0" FontSize="15" Text="Welcome"/>
<Label TextColor="White" Margin="10,0,0,0" FontSize="20" Text="Dolapo"/>
</StackLayout>
</yummy:PancakeView>
Frame
widget does not allow individual corners to be changed, you can of course do this via a custom renderer per platform. i.e. on iOS, you can add a mask layer to the control, the stackoverflow.com/a/43877570/4984832 – SushiHangover