I need to set the corners of a frame rounded but my code doesn't work. I think that the problem is that i have two StackLayout with BackgroundColor. Why with IsClippedToBounds="True" doesn't work?
and this is the code:
<Frame CornerRadius="20"
Margin="15,7,15,7"
Padding="0"
IsClippedToBounds="True">
<Grid
IsClippedToBounds="True"
ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0"
Grid.Column="0"
BackgroundColor="{DynamicResource DarkGray}"
Padding="10">
<Label>...<Label>
</StackLayout>
<StackLayout Grid.Row="0"
Grid.Column="1"
BackgroundColor="{DynamicResource DarkGrayVariant}"
Padding="10">
<Image>...</Image>
</StackLayout>
</Grid>
</Frame>
You can create a custom renderer for corner radius on a frame. First of all, create a custom control that inherits from a frame in your portable project as:
public class ExtendedFrame : Frame
{
public new Thickness Padding { get; set; } = 0;
public int BorderThickness { get; set; }
public ExtendedFrame()
{
base.Padding = this.Padding;
}
}
You can then implement the renderer as below:
For Android:
public class ExtendedFrameRenderer : FrameRenderer
{
GradientDrawable _gi;
public ExtendedFrameRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
var origFrame = e.NewElement as ExtendedFrame;
if(origFrame != null)
{
GradientDrawable gi = new GradientDrawable();
_gi = gi;
gi.SetStroke(origFrame.BorderThickness, origFrame.OutlineColor.ToAndroid());
gi.SetColor(origFrame.BackgroundColor.ToAndroid());
gi.SetCornerRadius(origFrame.CornerRadius);
#pragma warning disable CS0618 // Type or member is obsolete
SetBackgroundDrawable(gi);
#pragma warning restore CS0618 // Type or member is obsolete
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (ChildCount > 0 && _gi != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
SetBackgroundDrawable(_gi);
#pragma warning restore CS0618 // Type or member is obsolete
}
base.OnElementPropertyChanged(sender, e);
}
}
For IOS:
public class ExtendedFrameRenderer : FrameRenderer
{
private ExtendedFrame customFrame;
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
customFrame = e.NewElement as ExtendedFrame;
SetupLayer();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName ||
e.PropertyName == Xamarin.Forms.Frame.OutlineColorProperty.PropertyName ||
e.PropertyName == Xamarin.Forms.Frame.HasShadowProperty.PropertyName ||
e.PropertyName == Xamarin.Forms.Frame.CornerRadiusProperty.PropertyName)
{
SetupLayer();
}
}
void SetupLayer()
{
float cornerRadius = customFrame.CornerRadius;
if (cornerRadius == -1f)
cornerRadius = 5f; // default corner radius
Layer.CornerRadius = cornerRadius;
Layer.BackgroundColor = customFrame.BackgroundColor.ToCGColor();
if (customFrame.HasShadow)
{
Layer.ShadowRadius = 2;
Layer.ShadowColor = UIColor.Black.CGColor;
Layer.ShadowOpacity = 0.3f;
Layer.ShadowOffset = new SizeF();
}
else
Layer.ShadowOpacity = 0;
//if (customFrame.OutlineColor == Color.Default)
// Layer.BorderColor = UIColor.Clear.CGColor;
//else
//{
Layer.BorderColor = customFrame.OutlineColor.ToCGColor();
Layer.BorderWidth = customFrame.BorderThickness;
// }
Layer.RasterizationScale = UIScreen.MainScreen.Scale;
Layer.ShouldRasterize = true;
}
}