The newest version of the Skype for iOS app has a lot of neat eye candy in it. I love all the animations it uses throughout the experience. If you are not familiar with what I am talking about, take a quick look at Brian Lovin’s Design Details blog on Skype. I wanted to try and recreate some of these animations in a Xamarin.Forms app, but I wasn’t sure how to go about it. A quick search brought up this post by Arkadiusz Holko. It’s not a perfect recreation, but it’s a pretty good start!
Arkadiusz put his solution on GitHub, so I decided to see what I could learn from that and port it to a Xamarin.Forms project. My goal was to not use custom renderers and make everything in shared code. Here is a list of things I figured would be needed:
- Some way to animate a view with an easing function that looks similar
- Access to a drawing API to draw some paths on a view
- All of this would need to be shared code / cross-platform
Not too bad, right?
Wrong
Ok, so it’s not so bad. Xamarin.Forms already has some lovely animation routines for doing all sorts of cool stuff. There are also some easing functions already available to us. The Easing.SpringOut
method looked like what I wanted, and the LayoutTo()
method will move my view around just fine. The next problem is the drawing API. Without custom renderers, I didn’t find a great way to do custom drawing on a Xamarin.Forms.ContentView. Fortunately, someone else already solved this for me. I came across Christian Falch’s NControl library. Listen to this:
The library contains the NControlView class where real custom cross-platform drawing can be performed without the need for native implementations thanks to the NGraphics library.

I quickly followed along and had something pretty similar going in my Forms app.

The next big issue here is that the side view (green) is moving in sync with the center (red) view. This is not what we want. The reason this is happening is because the easing functions are identical. We need some way to control the coefficients of the easing methods so we can change the elasticity of the animation.
Easing
Instead of passing the built in Easing.SpringOut
, we can instead create a custom easing function. The Easing
class has an overload that takes a Func<double, double>
. The only criteria is that when given 0, the function returns 0, and when given 1, it will return 1. Here is what I ended up with:
new Easing((x) => {
return ((x - 1) * (x - 1) * (( sidecoeff + 1 ) * (x - 1) + sidecoeff) + 1);
})
see here for the original BackEaseOut method used. Simplification explained here
And the result after some tweaking.

The Bezier
I made use of the NControl library so that I could draw a bezier curve from these control points. I ended up with something like this:
public override void Draw (NGraphics.ICanvas canvas, NGraphics.Rect rect)
{
base.Draw (canvas, rect);
double yOffset = 20;
double width = rect.Width;
double height = rect.Height;
var points = new PathOp[] {
new MoveTo(0, yOffset - delta),
new CurveTo(new NGraphics.Point(width / 2, yOffset + delta),
new NGraphics.Point(width / 2, yOffset + delta),
new NGraphics.Point(width, yOffset - delta)),
new LineTo(width, height),
new LineTo(0, height)
};
canvas.DrawPath(points, null, new SolidBrush(new NGraphics.Color(0, 0.722, 1, 1)));
}
Arkadiusz’s post talks about using CADisplayLink
to get a calback for each frame of the animation where the curve can be updated. I did not find a great place to do something similar in shared code, so I put it in the custom easing method which I figured is called similarly.
_sideHelperView.LayoutTo(position, _animationDuration, new Easing((x) => {
UpdateCurve();
return ((x - 1) * (x - 1) * (( sidecoeff + 1 ) * (x - 1) + sidecoeff) + 1);
}));
The UpdateCurve()
method simply calculates the delta of the side and center helper views and calls Invalidate()
on the actual NControlView
being drawn. This means that each time the easing method is called, the view will be invalidated and cause the curve to be updated each step of the animation. The end result is pretty good.


On my device testing, the animation was smooth on both Android and iOS. There is plenty of room for optimizations and eye candy! Also, if you have not already, I encourage you to stop by Arkadiusz’s GitHub page and take a look at the work he’s done.