Migrating Animations from Xamarin Forms to Uno Platform

Animations are crucial in making any user interface more engaging and dynamic, regardless of complexity. This article will delve into the process of migrating animations from Xamarin Forms to Uno Platform This article will delve into the process of migrating animations from Xamarin Forms to Uno Platform, a question we get asked reasonably frequently, so we are documenting it for ease of access. Furthermore, we’ll look at simpler and more complex animations such as the ones below, highlight the differences between the two platforms, and provide the necessary steps to make the process seamless and practical. By the end of this article, you’ll better understand how to create animations that work seamlessly across multiple platforms.

Getting Animated

Even the simplest animations can help bring your user interface to life. Xamarin Forms uses a set of extension methods provided by the ViewExtensions class to animate a common set of UI element properties. Under the hood, these are powered by the Animation class, which allows you to define custom animations on other properties. This uses callback functions which define the property change itself. The Animation is created with an easing function and will call the callback as required. Callbacks can be written inline; for example the following defines a scale animation for an Image:

				
					var animation = new Animation (v => image.Scale = v, 1, 2); 
				
			

Animations can be coordinated together by adding child animations to an Animation object. When specifying the start and endpoints of child animations, they are as a proportion (from 0.0 to 1.0) of the entire animation; the duration of the whole animation is only specified when you run it. This is done by calling the Commit method of the parent animation, where you give the animation a unique name, a frequency (number of updates per second) and duration in milliseconds. The animation can fire a callback method when complete. In Xamarin Forms, all animations are described in code only and for simple scenarios with the extension methods will mean a single line of code to add a basic animation. 

Storyboards

WinUI, and hence Uno Platform, uses a concept called Storyboards which allows you to trigger one or more animations in a coordinated way. Storyboards in WinUI are a direct descendent of those introduced in Microsoft’s original XAML platform – WPF. They have been used in WPF, Silverlight, UWP and WinUI with minimal changes. Because the storyboard animation system allows you to chain together multiple animations which can operate on any dependency property, they are very powerful. There is a strong similarity between a storyboard and a parent Animation in Xamarin Forms. 

Of course, the more animations you perform concurrently, the more pressure you put on the graphics system in your device, so you need to be careful to strike the right balance and perform testing on a range of target devices to ensure a smooth experience for users. 

A Storyboard can contain one or more animation items. There are a few different types of animation, but the most used is DoubleAnimation. There are several key properties which define the behaviour of the animation. From and To values define the values you animate between. Depending on the property you are animating, these could be 0.0 to 1.0 to fade in the opacity of an element or a range of angles to rotate an item.  

Each animation must contain a Duration to define how long it runs. This is a Duration type, a special structure containing a nested TimeSpan. In practice, you will most likely use a finite timespan and not the special values of Automatic or Forever. In XAML, you can define the timespan as text, which will be parsed. This is a big difference from the Xamarin approach, as all times in the animations are defined in real-time spans rather than proportionally. 

Simple Animations

Having seen how the Xamarin Forms and WinUI approaches differ, let’s look at a simple example from both. In Xamarin Forms, you would use the following to animate the opacity of an element from within a button click handler:

				
					await myRectangle.FadeTo(0.0, 1000); 
				
			

The equivalent Storyboard would use the following in XAML:

				
					<Storyboard x:Name="FadeOutStoryboard"> 
    <DoubleAnimation 
        Storyboard.TargetName="MyRectangle" 
        Storyboard.TargetProperty="Opacity" 
        From="1.0" To="0.0" Duration="0:0:1"/> 
</Storyboard> 
				
			

Then you would trigger this storyboard from code using:

				
					FadeOutStoryboard.Begin(); 
				
			

As mentioned, you can create the complete storyboard in code. It’s more complex than the equivalent Xamarin Forms code, but more powerful too:

				
					var fadeOutStoryboard = new Storyboard(); 
var fadeAnimation = new DoubleAnimation { From = 1.0, To = 0.0, Duration = new Duration(TimeSpan.FromSeconds(1.0)) }; 
Storyboard.SetTarget(fadeAnimation, MoveableRectangle); 
Storyboard.SetTargetProperty(fadeAnimation, "Opacity"); 
fadeOutStoryboard.Children.Add(fadeAnimation); 
fadeOutStoryboard.Begin(); 
				
			

Because of the hierarchical nature of the XAML along with the built-in interpretation on the Duration property the XAML example can be easier to follow. Another advantage of the XAML approach is that you can store an animation as a named resource either on an individual view or reuse it in multiple locations in your app. 

It’s important to note that if you have created a storyboard with RepeatBehavior set to Forever you’ll need to call Pause or Stop on the storyboard, otherwise it will run until the associated page or control is cleaned up by the garbage collector. 

Xamarin Forms Animations and Their Equivalents

Xamarin Forms 

Storyboard Equivalent 

RotateTo 

RotateTransform.Angle 

ScaleTo 

ScaleTransform.ScaleX and ScaleTransform.ScaleY 

ScaleXTo 

ScaleTransform.ScaleX 

ScaleYTo 

ScaleTransform.ScaleY 

TranslateTo 

TranslateTransform.X and TranslateTransform.Y 

FadeTo 

Opacity 

 

Easing Functions

Not all animation is linear, an easing function changes the way the animation progresses so that the velocity changes. This enables items to speed up and slow down producing more natural movements and enables bouncing. Xamarin Forms uses the Easing class for a collection of reusable easing functions covering the common easing types. Each has In and Out variants depending on where they sit in an animation sequence. For Cubic and Sine animations there are InOut variants which accelerate in and decelerate out. Xamarin Forms supported custom easing functions so you can define your own progression from 0.0-1.0 to be used across your animation sequence. WinUI doesn’t currently support custom easing, so you’ll need to replace these with the closest available easing function or use key-frame animation to specify required values along the timeline. The table below shows the mappings between Xamarin Forms and WinUI:- 

Xamarin Forms 

WinUI 

Bounce (BounceIn/BounceOut) 

BounceEase 

Cubic (CubicIn/CubicInOut/CubicOut 

CubicEase 

Linear 

(specify no EasingFunction) 

Sin (SinIn/SinInOut/SinOut) 

SineEase 

Spring (SpringIn/SpringOut) 

ElasticEase 

 The easing functions in WinUI have an EasingMode property where you can set EaseIn, EaseOut or EaseInOut. WinUI adds some additional standard easing functions such as QuadraticEase and PowerEase the latter of which allows you to accelerate or decelerate using any power which gives more flexibility over the standard CubicEase. There is also BackEase which reverses the direction slightly before starting (or overshoots on ending in the case of an EaseOut animation). 

Concurrent Animations

If you want to run multiple concurrent animations in Xamarin Forms then you call the relevant extension method but omit the await keyword from the first e.g. 

				
					control1.RotateTo(90); 

await control2.RotateTo(180); 
				
			

In Uno, and WinUI, a Storyboard is designed to contain multiple animations, so you add these either in XAML or C# and set the same BeginTime. You can omit BeginTime if you want them to start at the beginning of the timeline.  

Complex Animations

This is where Storyboards start to really shine because you have so much control over the start time and duration of individual animations and can orchestrate very complex sequences. The following is an example of complex animation in Xamarin Forms:

				
					var parentAnimation = new Animation (); 
var scaleUpAnimation = new Animation (v => image.Scale = v, 1, 2, Easing.SpringIn); 
var rotateAnimation = new Animation (v => image.Rotation = v, 0, 360); 
var scaleDownAnimation = new Animation (v => image.Scale = v, 2, 1, Easing.SpringOut); 
parentAnimation.Add (0, 0.5, scaleUpAnimation); 
parentAnimation.Add (0, 1, rotateAnimation); 
parentAnimation.Add (0.5, 1, scaleDownAnimation); 
parentAnimation.Commit (this, "ChildAnimations", 16, 4000, null, null); 
				
			

The equivalent for Uno Platform is:

				
					<Storyboard x:Name="ComplexXamlStoryboard"> 
            <DoubleAnimationUsingKeyFrames 
               Storyboard.TargetName="RectangleScale" 
               Storyboard.TargetProperty="ScaleX"> 
                <EasingDoubleKeyFrame Value="2.0" KeyTime="0:0:2"> 
                    <EasingDoubleKeyFrame.EasingFunction> 
                        <ElasticEase EasingMode="EaseIn" Springiness="2" Oscillations="2" /> 
                    </EasingDoubleKeyFrame.EasingFunction> 
                </EasingDoubleKeyFrame> 
                <EasingDoubleKeyFrame Value="1.0" KeyTime="0:0:4"> 
                    <EasingDoubleKeyFrame.EasingFunction> 
                        <ElasticEase EasingMode="EaseOut" Springiness="2" Oscillations="2" /> 
                    </EasingDoubleKeyFrame.EasingFunction> 
                </EasingDoubleKeyFrame> 
            </DoubleAnimationUsingKeyFrames> 
            <DoubleAnimationUsingKeyFrames 
               Storyboard.TargetName="RectangleScale" 
               Storyboard.TargetProperty="ScaleY"> 
                <EasingDoubleKeyFrame Value="2.0" KeyTime="0:0:2"> 
                    <EasingDoubleKeyFrame.EasingFunction> 
                        <ElasticEase EasingMode="EaseIn" Springiness="2" Oscillations="2" /> 
                    </EasingDoubleKeyFrame.EasingFunction> 
                </EasingDoubleKeyFrame> 
                <EasingDoubleKeyFrame Value="1.0" KeyTime="0:0:4"> 
                    <EasingDoubleKeyFrame.EasingFunction> 
                        <ElasticEase EasingMode="EaseOut" Springiness="2" Oscillations="2" /> 
                    </EasingDoubleKeyFrame.EasingFunction> 
                </EasingDoubleKeyFrame> 
            </DoubleAnimationUsingKeyFrames> 
            <DoubleAnimation 
                Storyboard.TargetName="RectangleRotation" 
                Storyboard.TargetProperty="Angle" 
                From="0.0" To="360" Duration="0:0:4"/>
        </Storyboard> 
				
			

Note: that I have specified values for the Springiness and Oscillations to the ElasticEase as they initially felt more extreme than the Xamarin Spring easing.

Animating a Property Multiple Times

If you had an animation where you wanted to perform multiple changes to a property – e.g. translating an object through multiple points at different speeds then in Xamarin Forms you just chain together the required TranslateTo calls, or animations with the same callback. However, if you add multiple animations to a Storyboard which animate the same property, it will compile but you will receive an error at runtime. There is already a built-in solution to this – there are animations which allow you to specify multiple keyframes. For floating point properties we use the DoubleAnimationUsingKeyFrames. Rather than just setting From and To values you can now add multiple child keyframes which define where the animation should be at specified times. The following example shows a pair of keyframes used to fade a control to zero opacity and then back to solid again:

				
					<DoubleAnimationUsingKeyFrames 
   Storyboard.TargetName="MoveableRectangle" 
   Storyboard.TargetProperty="Opacity"> 
   <LinearDoubleKeyFrame Value="0.0" KeyTime="0:0:1"/> 
   <LinearDoubleKeyFrame Value="1.0" KeyTime="0:0:2"/> 
</DoubleAnimationUsingKeyFrames> 
				
			

Note here the use of LinearDoubleKeyFrame. This tells the animation system to animate from the current value to specified value on a linear basis – without using an easing function. There are two related keyframes for different behavior and you can mix and match within a DoubleAnimationUsingKeyFrames. The DiscreteDoubleKeyFrame tells the animation system to change immediately to that set value at the given time – like a kind of teleport. The EasingDoubleKeyFrame works like the linear version but allows you to specify any of the easing functions to move towards the new value in a non-linear way. One thing to note is that Uno doesn’t currently support the AutoReverse property on Storyboard which on WinUI replays the entire storyboard in reverse upon completion. Luckily there is a workaround which is to use keyframes to specify the reverse behavior. 

Wrapping Up

Animations in Xamarin Forms is quite simple when you make use of the handful of specific helpers. Because the animation is defined in code only, your only choices are to selectively include or exclude the await keyword to define if animations happen concurrently or in series. If you want to stagger start times you must use Task.Delay to add specific pauses. The Animation class allows you to create more complex groups of animation in code, but you must be aware that a lot of the orchestration must be done as proportions of the full animation time rather than explicit time values. 

Uno’s Storyboard model is flexible by allowing any dependency properties to be animated, and has more easing functions and more structure when animating the same properties through different steps using keyframes. The ability to express a Storyboard in either XAML or C# will also suit different coding styles. 

The source code used to demonstrate the animations described above can be downloaded here

About Uno Platform

For those new to the Uno Platform, it allows for creating pixel-perfect, single-source C# and XAML apps that run natively on Windows, iOS, Android, macOS, Linux and Web via WebAssembly. In addition, it offers Figma integration for design-development handoff and a set of extensions to bootstrap your projects. Uno Platform is free, open-source (Apache 2.0), and available on GitHub.

Next Steps

To upgrade to the latest release of Uno Platform, please update your packages to 4.8 via your Visual Studio NuGet package manager! If you are new to Uno Platform, following our official getting started guide is the best way to get started. (5 min to complete)

Share this post:
Join us for a live-webinar on everything Uno Platform 5.0 Dec 12th, at noon EST.
Save to calendar