Efficient way to add a shimmering effect to your Xamarin.Forms applications.
Add nuget package Xamarin.Essentials to all projects
Add Init method to App.cs
constructor:
InitializeComponent();
var density = Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density;
ShimmerLayout.Init(density);
add reference:
xmlns:controls="clr-namespace:XFShimmerLayout.Controls;assembly=XFShimmerLayout"
Paste content inside shimmerLayout:
<controls:ShimmerLayout Angle="-45" GradientSize=".2" IsLoading="True">
<!--Yours awesome view-->
</controls:ShimmerLayout>
ShimmerLayout processes the visual tree and by using Skia, tries to draw every element.
e.g. if we have included this layout into the ShimmerLayout
<StackLayout Spacing="8">
<BoxView Margin="16" HeightRequest="20" WidthRequest="100" />
<BoxView Margin="16" HeightRequest="20" WidthRequest="200" />
</StackLayout>
The ShimmerLayout will create a Canvas Layer above this StackLayout and will draw every VisualElement, except Layouts. In fact, it will create a copy layer of this View (including the right margins and paddings) and draws every VisualElement to this. In the above example, it will draw 2 rectangles.
You can have as deep Visual Tree wants, the shimmer layout will draw a right copy of it.
You can set default CornerRadius and padding of overlay for every element,
<controls:ShimmerLayout
CornerRadiusOverlayDefault="10"
PaddingOverlayDefault="5" />
or set for single element using Attached Property
<controls:ShimmerLayout ... >
<BoxView
controls:ShimmerLayout.PaddingOverlay="7,1"
controls:ShimmerLayout.CornerRadiusOverlay="5"
... />
</controls:ShimmerLayout>
Before drawing the Canvas, we must specify a Shader. We used a LinearGradient Shader.
First of all, we must extract the 2 points from the specified Angle. This can be done with some maths and knowing that the diagonal distance of the triangle is Math.Pow(2, -0.5);
. The method that extracts the 2 points from the angle is in SkiaExtensions.cs
and called public static IEnumerable<Point> ToPoints(this double angle)
.
The 2 points that we've got are in the range of [0,1]. So we must convert them to the actual width and height. This can be done easily by multiply e.g. the point with the width or height.
For the Gradient we must got 2 Points, the Start Point and the End Point:
The method that is responsible for the Drawing is the OnMaskCanvasPaintSurface
of the ShimmerLayout
To make the animation happen, we need startX and endX:
We created an animation that animates a value from the StartX to EndX and every time we InvalidateSurface
of the Canvas
.