Hi friends. Nearly every application nowadays talks to APIs or processes data from an internal database. These tasks are time consuming and most of the time are done in the foreground. Since they are done in the foreground, we have to inform the user that some important work is going on. The most basic way in Xamarin Forms of telling the user that some work is being done by the app is to use a simple “Activity Indicator”. Though this approach is acceptable, it is not very “a la mode”. What is often seen nowadays is the use of a view that has the shape of the underlying UI with animations. This view is comonly refered to as the Skeleton Loader. So, today we will create a simple Skeleton Loader in Xamarin Forms.
Here is the source code for this article
Creating A Skeleton Loader in Xamarin Forms
First, we need to break down what it takes to build a skeleton loader, then use what Xamarin offers us to implement this control. Basically, a skeleton loader is just a view that can have different shapes (square, rectangle, circle), that appear only when we are loading data and that contains some sort of color animation.
Taking this into consideration, we can use;
- Xamarin Community’s StateView to detect loading (show the control) and success states (hide the control).
- Then we use the Boxview to create our control (shapes and rounded corners)
- To animate, we simply use Xamarin’s animation API to make beautiful color animations
Implementation
First, we make a new control that inherits from the Box view.
1 | SkeletonView : BoxView |
Then we add the appropriate properties. (The colors that will be used to animate the view, and an IsLoading property, to determine when the view is loading).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public static readonly BindableProperty StartColorProperty = BindableProperty.Create("StartColor", typeof(Color), typeof(SkeletonView), default(Color)); public Color StartColor { get { return (Color)GetValue(StartColorProperty); } set { SetValue(StartColorProperty, value); } } public static readonly BindableProperty EndColorProperty = BindableProperty.Create("EndColor", typeof(Color), typeof(SkeletonView), default(Color)); public Color EndColor { get { return (Color)GetValue(EndColorProperty); } set { SetValue(EndColorProperty, value); } } public bool IsLoading { get { return (bool)GetValue(IsLoadingProperty); } set { SetValue(IsLoadingProperty, value); } } |
To animate the view, we will trigger an animation every time the “IsLoading” property is set to true. Skeleton loaders usually have two types of animations. The first and the most simple is a “Color Animation” where two colors fluctuate in a timely fashion. The second is a “Gradient” animation. Where we have a change in gradient of colors regularly. We will implement both. First, we implement the color animation. To learn more about animations. To learn more about custom animations, in Xamarin Forms, check this doc.
If you find this article useful, please follow me on Twitter,  Github, Linkedin, or like my Facebook page to stay updated.Follow me on social media and stay updated
1 2 3 4 5 6 7 8 9 10 11 | void RunSkeletonColorAnimation() { Func<double, Color> transform = (t) => Color.FromRgba(StartColor.R + t * (EndColor.R - StartColor.R), StartColor.G + t * (EndColor.G - StartColor.G), StartColor.B + t * (EndColor.B - StartColor.B), StartColor.A + t * (EndColor.A - StartColor.A)); this.Animate<Color>(LoadingAnimationName, transform, (color) => BackgroundColor = color, repeat: () => true, length: 2000); } |
In the above function, “LoadingAnimationName” stands for the name of the animation. Whereas “transform” is a function that takes as parameter a value “t”. This value increments gradually from 0 to 1 within 2000 milliseconds(length). Then, we use this “t” value to determine the color variations and return the new color. The new color is then assigned to the “Background” property of our control every time it is computed. we also specify that this process should be repeated. We then do the same for gradient animations as seen below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | void RunSkeletonGradientAnimation() { Func<double, (Color startColor, Color endColor)> transform = (t) => { var startColor = Color.FromRgba(StartColor.R + t * (EndColor.R - StartColor.R), StartColor.G + t * (EndColor.G - StartColor.G), StartColor.B + t * (EndColor.B - StartColor.B), StartColor.A + t * (EndColor.A - StartColor.A)); var endColor = Color.FromRgba(StartColor.R - t * (EndColor.R - StartColor.R), StartColor.G + t * (StartColor.G - EndColor.G), StartColor.B + t * (StartColor.B - EndColor.B), StartColor.A + t * (StartColor.A - EndColor.A)); return (startColor, endColor); }; this.Animate<(Color startColor, Color endColor)>(LoadingAnimationName, transform, (color) => { Background = new LinearGradientBrush { StartPoint = new Point(0, 0), EndPoint = new Point(1, 0), GradientStops = new GradientStopCollection { new GradientStop(color.startColor, 0.1f), new GradientStop(color.endColor, 0.0f) } }; }, repeat: () => true, length: 1000); } |
We put our control in a state layout then, assign to it the loading state so that it is visible only when we load content. We can give it the shape we want, and position it as we want in a grid. Or in our case, make it look like a rectangle and ask it to repeat the shape 5 times in the state view. To learn more about state views and state layout, follow this link.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <xct:StateView StateKey="Loading" RepeatCount="5" Margin="5,10"> <xct:StateView.Template> <DataTemplate> <Grid> <customViews:SkeletonView StartColor="LightGray" EndColor="Gray" IsLoading="True" Margin="10,7" HeightRequest="50"/> </Grid> </DataTemplate> </xct:StateView.Template> </xct:StateView> |
Conclusion
With just a few lines of code, we implemented a skeleton loader. You can check the whole source code here. It has become easier to implement such controls in Xamarin Forms. With just a little bit of effort, you can do good-looking controls. To learn about implementing a robust media player capable of streaming media of nearly every format and every source, check out this article.
Follow me on social media and stay updated