0
votes

When I create a custom renderer for Xamarin Forms Frame in Android, CornerRadius property goes for a toss. No matter what I set it to, it doesn't work. It always draw a rectangle.

Xamarin Forms (Control) -

public class MyFrame : Frame
{
}

Xamarin Forms (XAML) -

<shd:MyFrame WidthRequest="200" HeightRequest="200" CornerRadius="100">
    <shd:MyFrame.Content>
        <Label Text="Hello" TextColor="Black"/>
    </shd:MyFrame.Content>
</shd:MyFrame>

Xamarin Android -

public class MyFrameRenderer : ViewRenderer<Controls.MyFrame, FrameRenderer>
{
    public MyFrameRenderer(Context context) : base(context)
    {

    }

    protected override void OnElementChanged(ElementChangedEventArgs<Controls.MyFrame> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
        }
    }
}

How do I set CornerRadius property to give it rounded corners.

Thanks!

Update

Neumorphism is design trend, where control have two shades of shadow, dark and light. If you visit this website you can visualize what I am trying to achieve.

I used Android's 9 patch image to achieve similar effect for a rectangular frame, however, when I tried to provide CornerRadius to it, it didn't worked.

3
What is your requirement? Frames defaultly provide corner radius. Are you trying to draw circular frame? - Anand
Yes.With a 9 patch image for Android(Neumorphic shadow). - Gaurav Mathur
Hi , could you share the wanted effects of Frame your want , I will check that . - Junior Jiang
@GauravMathur Xamarin forms has a nuget package about 9 patch image , you can have a try wtih this in each iOS or Android platform .baskren.github.io/Forms9Patch/guides/… - Junior Jiang

3 Answers

0
votes

Try this

Setting corner radius half of height and width and setting padding to 0 .

 <Frame  HeightRequest="100" Padding="0" HorizontalOptions="Center" HasShadow="True" BackgroundColor="Accent" IsClippedToBounds="True" WidthRequest="100" CornerRadius="50">
            <Image Source="yourimage.png" Aspect="AspectFill"></Image>
 </Frame>
0
votes

You can have a try with Forms9Patch Nuget Package to implement it in each iOS and Android .Having a look at its document.

<StackLayout Padding=" 10">
    <!-- Place new controls here -->
    <Label Text="Welcome to Xamarin.Forms!" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Forms9Patch:Frame Padding="20"
                       HeightRequest="100"
                       WidthRequest="100"
                       OutlineColor="Blue"
                       OutlineWidth="3"
                       OutlineRadius="10"
                       HasShadow="True"
                       BorderRadius="50"
                       BackgroundColor="Gray">
        <!--<Label Text="Forms9Patch.Frame w/ OutlineWidth+OutlineRadius"
               TextColor="White"
               HorizontalOptions="Center"
               VerticalOptions="Center"
               FontSize="14" />-->

    </Forms9Patch:Frame>

</StackLayout>

The effect :

enter image description here

And if want to make image with different shapes , you can use its Forms9Patch.Image with Outline and Shape Properties

0
votes

How I did it.

Created a custom renderer for View. With properties for Main color, Dark shadow and Light shadow -

public class NeumorphicCircleBackground : View
{
    public static readonly BindableProperty LightColorProperty =
        BindableProperty.Create("LightColor", typeof(Color), typeof(NeumorphicCircleBackground), null);

    public Color LightColor
    {
        get { return (Color)GetValue(LightColorProperty); }
        set { SetValue(LightColorProperty, value); }
    }

    public static readonly BindableProperty MainColorProperty =
        BindableProperty.Create("MainColor", typeof(Color), typeof(NeumorphicCircleBackground), null);

    public Color MainColor
    {
        get { return (Color)GetValue(MainColorProperty); }
        set { SetValue(MainColorProperty, value); }
    }

    public static readonly BindableProperty DarkColorProperty =
        BindableProperty.Create("DarkColor", typeof(Color), typeof(NeumorphicCircleBackground), null);

    public Color DarkColor
    {
        get { return (Color)GetValue(DarkColorProperty); }
        set { SetValue(DarkColorProperty, value); }
    }
}

And an Android view -

protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);

        var h = canvas.Height;
        var w = canvas.Width;
        var size = Math.Min(h, w);

        float a = 0.1f * size;
        float b = 0.6f * size;
        float x0 = (w - size) / 2;
        float y0 = 0f;

        RectF ovalLight = new RectF();
        RectF ovalMain = new RectF();
        RectF ovalDark = new RectF();
        ovalLight.Set(x0, y0, x0 + b, y0 + b);
        ovalMain.Set(x0 + a, y0 + a, x0 + a + b, y0 + a + b);
        ovalDark.Set(x0 + 2 * a, y0 + 2 * a, x0 + 2 * a + b, y0 + 2 * a + b);

        var r = b / 2;

        var xl = x0 + b / 2;
        var yl = y0 + b / 2;
        var xd = x0 + 2 * a + b / 2;
        var yd = y0 + 2 * a + b / 2;
        var xm = x0 + a + b / 2;
        var ym = y0 + a + b / 2;

        var lightGradient = GetRadialPaint(xl, yl, r, _lightColor);
        var darkGradient = GetRadialPaint(xd, yd, r, _darkColor);
        var mainGradient = new Paint(PaintFlags.AntiAlias) { Color = _mainColor };

        if (_isCircle)
        {
            DrawCircle(canvas, xl, yl, r, lightGradient);
            DrawCircle(canvas, xd, yd, r, darkGradient);
            DrawCircle(canvas, xm, ym, r, mainGradient);
        }
        else
        {
            DrawRoundedRectangle(canvas, ovalLight, 50f, 50f, lightGradient);
            DrawRoundedRectangle(canvas, ovalDark, 50f, 50f, darkGradient);
            DrawRoundedRectangle(canvas, ovalMain, 50f, 50f, mainGradient);
        }
    }

I have added further properties for making it a generic Rounded Corner Rectangle as well as a perfect circle. You can modify it the way you want.