Simple Animations in Xamarin.Forms
The ViewExtensions class provides extension methods that can be used to construct simple animations. This article demonstrates creating and canceling animations using the ViewExtensions class.
The ViewExtensions
class provides the following extension methods that can be used to create simple animations:
CancelAnimations
cancels any animations.FadeTo
animates theOpacity
property of aVisualElement
.RelScaleTo
applies an animated incremental increase or decrease to theScale
property of aVisualElement
.RotateTo
animates theRotation
property of aVisualElement
.RelRotateTo
applies an animated incremental increase or decrease to theRotation
property of aVisualElement
.RotateXTo
animates theRotationX
property of aVisualElement
.RotateYTo
animates theRotationY
property of aVisualElement
.ScaleTo
animates theScale
property of aVisualElement
.ScaleXTo
animates theScaleX
property of aVisualElement
.ScaleYTo
animates theScaleY
property of aVisualElement
.TranslateTo
animates theTranslationX
andTranslationY
properties of aVisualElement
.
By default, each animation will take 250 milliseconds. However, a duration for each animation can be specified when creating the animation.
Note
The ViewExtensions
class provides a LayoutTo
extension method. However, this method is intended to be used by layouts to animate transitions between layout states that contain size and position changes. Therefore, it should only be used by Layout
subclasses.
The animation extension methods in the ViewExtensions
class are all asynchronous and return a Task<bool>
object. The return value is false
if the animation completes, and true
if the animation is cancelled. Therefore, the animation methods should typically be used with the await
operator, which makes it possible to easily determine when an animation has completed. In addition, it then becomes possible to create sequential animations with subsequent animation methods executing after the previous method has completed. For more information, see Compound Animations.
If there's a requirement to let an animation complete in the background, then the await
operator can be omitted. In this scenario, the animation extension methods will quickly return after initiating the animation, with the animation occurring in the background. This operation can be taken advantage of when creating composite animations. For more information, see Composite Animations.
For more information about the await
operator, see Async Support Overview.
Single Animations
Each extension method in the ViewExtensions
implements a single animation operation that progressively changes a property from one value to another value over a period of time. This section explores each animation operation.
Rotation
The following code example demonstrates using the RotateTo
method to animate the Rotation
property of an Image
:
await image.RotateTo (360, 2000);
image.Rotation = 0;
This code animates the Image
instance by rotating up to 360 degrees over 2 seconds (2000 milliseconds). The RotateTo
method obtains the current Rotation
property value for the start of the animation, and then rotates from that value to its first argument (360). Once the animation is complete, the image's Rotation
property is reset to 0. This ensures that the Rotation
property doesn't remain at 360 after the animation concludes, which would prevent additional rotations.
The following screenshots show the rotation in progress on each platform:
Note
In addition to the RotateTo
method, there are also RotateXTo
and RotateYTo
methods that animate the RotationX
and RotationY
properties, respectively.
Relative Rotation
The following code example demonstrates using the RelRotateTo
method to incrementally increase or decrease the Rotation
property of an Image
:
await image.RelRotateTo (360, 2000);
This code animates the Image
instance by rotating 360 degrees from its starting position over 2 seconds (2000 milliseconds). The RelRotateTo
method obtains the current Rotation
property value for the start of the animation, and then rotates from that value to the value plus its first argument (360). This ensures that each animation will always be a 360 degrees rotation from the starting position. Therefore, if a new animation is invoked while an animation is already in progress, it will start from the current position and may end at a position that is not an increment of 360 degrees.
The following screenshots show the relative rotation in progress on each platform:
Scaling
The following code example demonstrates using the ScaleTo
method to animate the Scale
property of an Image
:
await image.ScaleTo (2, 2000);
This code animates the Image
instance by scaling up to twice its size over 2 seconds (2000 milliseconds). The ScaleTo
method obtains the current Scale
property value (default value of 1) for the start of the animation, and then scales from that value to its first argument (2). This has the effect of expanding the size of the image to twice its size.
The following screenshots show the scaling in progress on each platform:
Note
In addition to the ScaleTo
method, there are also ScaleXTo
and ScaleYTo
methods that animate the ScaleX
and ScaleY
properties, respectively.
Relative Scaling
The following code example demonstrates using the RelScaleTo
method to animate the Scale
property of an Image
:
await image.RelScaleTo (2, 2000);
This code animates the Image
instance by scaling up to twice its size over 2 seconds (2000 milliseconds). The RelScaleTo
method obtains the current Scale
property value for the start of the animation, and then scales from that value to the value plus its first argument (2). This ensures that each animation will always be a scaling of 2 from the starting position.
Scaling and Rotation with Anchors
The AnchorX
and AnchorY
properties set the center of scaling or rotation for the Rotation
and Scale
properties. Therefore, their values also affect the RotateTo
and ScaleTo
methods.
Given an Image
that has been placed at the center of a layout, the following code example demonstrates rotating the image around the center of the layout by setting its AnchorY
property:
double radius = Math.Min(absoluteLayout.Width, absoluteLayout.Height) / 2;
image.AnchorY = radius / image.Height;
await image.RotateTo(360, 2000);
To rotate the Image
instance around the center of the layout, the AnchorX
and AnchorY
properties must be set to values that are relative to the width and height of the Image
. In this example, the center of the Image
is defined to be at the center of the layout, and so the default AnchorX
value of 0.5 does not require changing. However, the AnchorY
property is redefined to be a value from the top of the Image
to the center point of the layout. This ensures that the Image
makes a full rotation of 360 degrees around the center point of the layout, as shown in the following screenshots:
Translation
The following code example demonstrates using the TranslateTo
method to animate the TranslationX
and TranslationY
properties of an Image
:
await image.TranslateTo (-100, -100, 1000);
This code animates the Image
instance by translating it horizontally and vertically over 1 second (1000 milliseconds). The TranslateTo
method simultaneously translates the image 100 pixels to the left, and 100 pixels upwards. This is because the first and second arguments are both negative numbers. Providing positive numbers would translate the image to the right, and down.
The following screenshots show the translation in progress on each platform:
Note
If an element is initially laid out off screen and then translated onto the screen, after translation the element's input layout remains off screen and the user can't interact with it. Therefore, it's recommended that a view should be laid out in its final position, and then any required translations performed.
Fading
The following code example demonstrates using the FadeTo
method to animate the Opacity
property of an Image
:
image.Opacity = 0;
await image.FadeTo (1, 4000);
This code animates the Image
instance by fading it in over 4 seconds (4000 milliseconds). The FadeTo
method obtains the current Opacity
property value for the start of the animation, and then fades in from that value to its first argument (1).
The following screenshots show the fade in progress on each platform:
Compound Animations
A compound animation is a sequential combination of animations, and can be created with the await
operator, as demonstrated in the following code example:
await image.TranslateTo (-100, 0, 1000); // Move image left
await image.TranslateTo (-100, -100, 1000); // Move image diagonally up and left
await image.TranslateTo (100, 100, 2000); // Move image diagonally down and right
await image.TranslateTo (0, 100, 1000); // Move image left
await image.TranslateTo (0, 0, 1000); // Move image up
In this example, the Image
is translated over 6 seconds (6000 milliseconds). The translation of the Image
uses five animations, with the await
operator indicating that each animation executes sequentially. Therefore, subsequent animation methods execute after the previous method has completed.
Composite Animations
A composite animation is a combination of animations where two or more animations run simultaneously. Composite animations can be created by mixing awaited and non-awaited animations, as demonstrated in the following code example:
image.RotateTo (360, 4000);
await image.ScaleTo (2, 2000);
await image.ScaleTo (1, 2000);
In this example, the Image
is scaled and simultaneously rotated over 4 seconds (4000 milliseconds). The scaling of the Image
uses two sequential animations that occur at the same time as the rotation. The RotateTo
method executes without an await
operator and returns immediately, with the first ScaleTo
animation then beginning. The await
operator on the first ScaleTo
method call delays the second ScaleTo
method call until the first ScaleTo
method call has completed. At this point the RotateTo
animation is half way completed and the Image
will be rotated 180 degrees. During the final 2 seconds (2000 milliseconds), the second ScaleTo
animation and the RotateTo
animation both complete.
Running Multiple Asynchronous Methods Concurrently
The static
Task.WhenAny
and Task.WhenAll
methods are used to run multiple asynchronous methods concurrently, and therefore can be used to create composite animations. Both methods return a Task
object and accept a collection of methods that each return a Task
object. The Task.WhenAny
method completes when any method in its collection completes execution, as demonstrated in the following code example:
await Task.WhenAny<bool>
(
image.RotateTo (360, 4000),
image.ScaleTo (2, 2000)
);
await image.ScaleTo (1, 2000);
In this example, the Task.WhenAny
method call contains two tasks. The first task rotates the image over 4 seconds (4000 milliseconds), and the second task scales the image over 2 seconds (2000 milliseconds). When the second task completes, the Task.WhenAny
method call completes. However, even though the RotateTo
method is still running, the second ScaleTo
method can begin.
The Task.WhenAll
method completes when all the methods in its collection have completed, as demonstrated in the following code example:
// 10 minute animation
uint duration = 10 * 60 * 1000;
await Task.WhenAll (
image.RotateTo (307 * 360, duration),
image.RotateXTo (251 * 360, duration),
image.RotateYTo (199 * 360, duration)
);
In this example, the Task.WhenAll
method call contains three tasks, each of which executes over 10 minutes. Each Task
makes a different number of 360 degree rotations – 307 rotations for RotateTo
, 251 rotations for RotateXTo
, and 199 rotations for RotateYTo
. These values are prime numbers, therefore ensuring that the rotations aren't synchronized and hence won't result in repetitive patterns.
The following screenshots show the multiple rotations in progress on each platform:
Canceling Animations
An application can cancel one or more animations with a call to the CancelAnimations
extension method, as demonstrated in the following code example:
image.CancelAnimations();
This will immediately cancel all animations that are currently running on the Image
instance.
Summary
This article demonstrated creating and canceling animations using the ViewExtensions
class. This class provides extension methods that can be used to construct simple animations that rotate, scale, translate, and fade VisualElement
instances.