Customising Frame shadow in Xamarin Forms with Blur option using SkiaSharp. Everything you need to know!

TharsanP
XamarinLife
Published in
4 min readAug 5, 2020

--

Hello everyone after a long break great to catch you all with new custom Frame shadow story today. I have already discussed about customising shadow in one of my previous story. Adding to that, this story i am gonna discuss about how to add more options like blur.
Put on you seat belts guys its sure gonna be a roller coster ride and i am sure you gonna love this.

Custom Frame Shadow in Xamrin Forms — XamarinLife

I have created custom Shadow control using SkiaSharp to allow shadow effect and blur options to the dropShadow. So lets get started.

Versions:

Xamarin Forms : 4.7.0.1239

Skia Sharp:2.80.1

Add Nugets:

Add Skia Sharp Nuget to all the projects PCL,Android and iOS.

Add SkiaSharp Nuget — XamarinLife

Implementation

This impelementation is common for both platforms Andorid and iOS. So, nothing to impelement with native code.

I am creating a CustomFrame.cs class which is a custom control an new Element with bindable properties. This class impelements SKCanvasView. So, we have an override method called OnPaintSurface() where we draw the element and do the paintings with SKCanvas.

CustomFrame.cs

CustomFrame.cs — XamarinLife

I have several bindable properties that is used to here such as,

OffsetX — shadow offset value in X Axis

OffsetY — shadow offset value in Y Axis

BlurX — shadow blurriness value in X Axis

Blur Y — shadow blurriness value un Y Axis

ShadowColor — Shadow color property(we can define the shadow color)

Radius — Corner radius of the rectangle we are drawing(this is different from Xamarin Forms Frame corner radius)

SKPaint in Skia is used to mention the color, strokewidth, antialias, strokecap, font, etc. properities of the element we are drawing in the surface. In SKPaint a property called ImageFileter is there. This property is going to help us achieve the shadow with blur.

paint.ImageFilter = SKImageFilter.CreateDropShadow(
OffsetX,
OffsetY,
BlurX,
BlurY,
ShadowColor.ToSKColor(),
SKDropShadowImageFilterShadowMode.DrawShadowAndForeground);

Set ImageFilter with the bindable properities so it reflect to the values we give. and finally draw round rectangle with the created paint and raidus,

canvas.DrawRoundRect(new SKRect(20f, 20f, info.Width-20 , info.Height-20),Radius,Radius, paint);

I am using DrawRoundRect for my purpose. why DrawRoundRect?
Well, we use Xamarin Forms Frame because it has feature to add corner radius property so anything inside that will reflect with corner radius. That’s why i am choosing DrawRoundRect over DrawRect.

All the bindable properites have been added with propertychanged event. so when a value is changed the propertychanged event will trigger and work accordingly,

public static void OnOffsetXChanged(BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
var control = bindable as CustomFrame;
control?.InvalidateSurface();
}

new value is set, but need to redraw the surface with new value this is where InvalidateSurface() will do the trick for us. This function calls out the OnPaintSurface() method where the surface will be redrawn with new values. boom 💥.

Problem :

Even though this works fine with drawing an element which is a rounded rectangle when you try to use this in Xamarin Forms Page you will be facing issues fitting a content, fitting a iamge inside this rectange. you will be messed up with.

Solution:

Thats why i am creating a new custom control that can be easily used in Xamarin Forms Page with inside content no need to worry about placing layouts inside this no need to go mad with paddings and margins to fit with custom frame.

Implementation

I have created a ShadowFrame.cs which implements a Grid as its base. and have a simple layout with customframe we have created earlier and a contentview. Why using Grid as the base? Its because if we place two elements in same row it overlaps and display the elemetns on upon other. if u use stacklayout it will be horizontal or vertical and your created element will be in one place and the content will be placed below or after according to stacklayout orientation.

<?xml version=”1.0" encoding=”UTF-8"?>
<Grid xmlns=”http://xamarin.com/schemas/2014/forms"
xmlns:x=”http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local=”clr-namespace:CustomFrameWithSkia.CustomRenderer”
x:Class=”CustomFrameWithSkia.CustomRenderer.ShadowFrame”>
<Grid>
<local:CustomFrame x:Name=”skiacontent” VerticalOptions=”FillAndExpand” HorizontalOptions=”FillAndExpand” ></local:CustomFrame>
<ContentView x:Name=”content” VerticalOptions=”FillAndExpand” HorizontalOptions=”FillAndExpand” Margin=”10.5">

</ContentView>
</Grid>
</Grid>

Even though we have used the customframe we can’t bind properties to that class from this element. so we need to create the same binding properties and additonally a content property that to get the inside content and display in the contentview.


public static readonly BindableProperty ContentProperty = BindableProperty.Create(“Content”, typeof(View), typeof(ShadowFrame), null, BindingMode.TwoWay, propertyChanged: OnContentChanged);
public static void OnContentChanged(BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
var control = bindable as ShadowFrame;
control.content.Content = (View)newValue;
}
public View Content
{
get { return (View)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}

ShadowFrame.cs

Thats it guys all the work done now we can use this element in our page anywhere. for exmaple i have created a page to show content inside the custom frame control, That goes like below,

<local:ShadowFrame OffsetX=”{Binding OffsetX}” OffsetY=”{Binding OffsetY}” BlurX=”{Binding BlurX}” BlurY=”{Binding BlurY}” VerticalOptions=”CenterAndExpand” HorizontalOptions=”CenterAndExpand” HeightRequest=”200" WidthRequest=”200" ShadowColor=”Gray” Radius=”20">
<local:ShadowFrame.Content>
<StackLayout Margin=”10">
<Label Text=”Test Label 1"></Label>
<Label Text=”Test Label 2"></Label>
<Label Text=”Test Label 3"></Label>
<Label Text=”Test Label 4"></Label>
<Label Text=”Test Label 5"></Label>
</StackLayout>
</local:ShadowFrame.Content>
</local:ShadowFrame>

You can place any content any layout inside this Content property which takes it as a Xamarin Forms View.

I have done experiment with view-model binding values for the bindable properties to show how it works. See the out put below how the shadow and blue works with content inside.

Custom frame shadow with blur in Xamarin Forms — XamrinLife

I have come with this small idea, you can improvise it with your requirements as you need. Source code is updated in GitHub. Xamarin Forms never been easier. Cheers ✌️

--

--

TharsanP
XamarinLife

Professional Android native Developer and Cross paltform mobile app developer using Xamarin Forms. <3 Mobile Development