Reputation: 307
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>
Upvotes: 2
Views: 3535
Reputation: 307
With the code of Shaw I reached the solution!
I deleted the frame and I replaced the two stacklayout inside the grid with two differents CustomRenderer, one for round the left corners and one for the right corners.
<Grid ColumnSpacing="0"
Padding="15,7,15,7">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<customRenders:LeftCornerRadiusFrame CornerRadius="5"
Grid.Row="0"
Grid.Column="0"
Padding="10"
BackgroundColor="{DynamicResource DarkGray}">
<Label>...</Label>
</customRenders:LeftCornerRadiusFrame>
<customRenders:RightCornerRadiusFrame Grid.Row="0"
Grid.Column="1"
CornerRadius="5"
Padding="10"
BackgroundColor="{DynamicResource DarkGrayVariant}">
<Image>...</Image>
</customRenders:RightCornerRadiusFrame>
</Grid>
In the Android renderer delete the constructor and replace:
gi.SetCornerRadius(origFrame.CornerRadius);
with:
//in LeftCornerRadiusFrameRenderer
gi.SetCornerRadii(new float[] { origFrame.CornerRadius, origFrame.CornerRadius, 0, 0, 0, 0, origFrame.CornerRadius, origFrame.CornerRadius });
//in RightCornerRadiusFrameRenderer
gi.SetCornerRadii(new float[] { 0, 0, origFrame.CornerRadius, origFrame.CornerRadius, origFrame.CornerRadius, origFrame.CornerRadius, 0, 0 });
In IOS Renderer (I haven't tested it yet) after the:
Layer.CornerRadius = cornerRadius;
put:
//in LeftCornerRadiusFrameRenderer
Layer.MaskedCorners = (CoreAnimation.CACornerMask)5;
//in RightCornerRadiusFrameRenderer
Layer.MaskedCorners = (CoreAnimation.CACornerMask)10;
Upvotes: 0
Reputation: 703
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;
}
}
Upvotes: 1