Споделяне чрез


Summary of Chapter 22. Animation

Note

This book was published in the spring of 2016, and has not been updated since then. There is much in the book that remains valuable, but some of the material is outdated, and some topics are no longer entirely correct or complete.

You've seen that you can create your own animations using the Xamarin.Forms timer or Task.Delay, but it is generally easier using the animation facilities provided by Xamarin.Forms. Three classes implement these animations:

Generally, animations target properties that are backed by bindable properties. This is not a requirement but these are the only properties that dynamically react to changes.

There is no XAML interface for these animations, but you can integrate animations into XAML using techniques discussed in Chapter 23. Triggers and Behaviors.

Exploring basic animations

The basic animation functions are extension methods found in the ViewExtensions class. These methods apply to any object that derives from VisualElement. The simplest animations target the transforms properties discussed in Chapter 21. Transforms.

The AnimationTryout demonstrates how the Clicked event handler for a Button can call the RotateTo extension method to spin the button in a circle.

The RotateTo method changes the Rotation property of the Button from 0 to 360 over the course of one-quarter second (by default). If the Button is tapped again, however, it does nothing because the Rotation property is already 360 degrees.

Setting the animation duration

The second argument to RotateTo is a duration in milliseconds. If set to a large value, tapping the Button during an animation starts a new animation beginning at the current angle.

Relative animations

The RelRotateTo method performs a relative rotation by adding a specified value to the existing value. This method allows the Button to be tapped multiple times, and each time increases the Rotation property by 360 degrees.

Awaiting animations

All the animation methods in ViewExtensions return Task<bool> objects. This means that you can define a series of sequential animations using ContinueWith or await. The bool completion return value is false if the animation finished without interruption or true if it was cancelled by the CancelAnimation method, which cancels all animations initiated by the other method in ViewExtensions that are set on the same element.

Composite animations

You can mix awaited and non-awaited animations to create composite animations. These are the animations in ViewExtensions that target the TranslationX, TranslationY, and Scale transform properties:

Notice that TranslateTo potentially affects both the TranslationX and TranslationY properties.

Task.WhenAll and Task.WhenAny

It is also possible to manage simultaneous animations using Task.WhenAll, which signals when multiple tasks have all concluded, and Task.WhenAny, which signals when the first of several tasks has concluded.

Rotation and anchors

When calling the ScaleTo, RelScaleTo, RotateTo, and RelRotateTo methods, you can set the AnchorX and AnchorY properties to indicate the center of scaling and rotation.

The CircleButton demonstrates this technique by revolving a Button around the center of the page.

Easing functions

Generally animations are linear from a start value to an end value. Easing functions can cause animations to speed up or slow down over their course. The last optional argument to the animation methods is of type Easing, a class that defines 11 static read-only fields of type Easing:

The In suffix indicates that the effect is at the beginning of the animation, Out means at the end, and InOut means that it's at the beginning and end of the animation.

The BounceButton sample demonstrates the use of easing functions.

Your own easing functions

You can also define you own easing functions by passing a Func<double, double> to the Easing constructor. Easing also defines an implicit conversion from Func<double, double> to Easing. The argument to the easing function is always in the range of 0 to 1 as the animation proceeds linearly from beginning to end. The function usually returns a value in the range of 0 to 1, but could be briefly negative or greater than 1 (as is the case with the SpringIn and SpringOut functions) or could break the rules if you know what you're doing.

The UneasyScale sample demonstrates a custom easing function, and CustomCubicEase demonstrates another.

The SwingButton sample also demonstrates a custom easing function, and also a technique of changing the AnchorX and AnchorY properties within a sequence of rotation animations.

The Xamarin.FormsBook.Toolkit library has a JiggleButton class that uses a custom easing function to jiggle a button when it's clicked. The JiggleButtonDemo sample demonstrates it.

Entrance animations

One popular type of animation occurs when a page first appears. Such an animation can be started in the OnAppearing override of the page. For these animations, its best to set up the XAML for how you want the page to appear after the animation, and then initialize and animate the layout from code.

The FadingEntrance sample uses the FadeTo extension method to fade in the contents of the page.

The SlidingEntrance sample uses the TranslateTo extension method to slide in the contents of the page from the sides.

The SwingingEntrance sample uses the RotateYTo extension method to animate the RotationY property. A RotateXTo method is also available.

Forever animations

At the other extreme, "forever" animations run until the program is terminated. These are generally intended for demonstration purposes.

The FadingTextAnimation sample uses FadeTo animation to fade two pieces of text in and out.

PalindromeAnimation displays a palindrome, and then sequentially rotates the individual letters by 180 degrees so they're all upside-down. Then the entire string is flipped 180 degrees to read the same as the original string.

The CopterAnimation sample rotates a simple BoxView helicopter while revolving it around the center of the screen.

RotatingSpokes revolves BoxView spokes around the center of the screen, and then rotates each spoke itself to create interesting patterns:

Triple screenshot of Rotating Spokes

However, progressively increasing the Rotation property of an element might not work in the long term, as the RotationBreakdown sample demonstrates.

The SpinningImage sample uses RotateTo, RotateXTo, and RotateYTo to make it seem as if a bitmap is rotating in 3D space.

Animating the bounds property

The only extension method in ViewExtensions not yet demonstrated is LayoutTo, which effectively animates the read-only Bounds property by calling the Layout method. This method is normally called by Layout derivatives as will be discussed in Chapter 26. CustomLayouts.

The LayoutTo method should be restricted to special purposes. The BouncingBox program uses it to compress and expand a BoxView as it bounces off the sides of a page.

The XamagonXuzzle sample uses LayoutTo to move tiles in an implementation of the classic 15-16 puzzle that displays a scrambled image rather than numbered tiles:

Triple screenshot of Xamarin Xuzzle

Your own awaitable animations

The TryAwaitableAnimation sample creates an awaitable animation. The crucial class that can return a Task object from the method and signal when the animation is completed is TaskCompletionSource.

Deeper into animations

The Xamarin.Forms animation system can be a little confusing. In addition to the Easing class, the animation system comprises the ViewExtensions, Animation, and AnimationExtension classes.

ViewExtensions class

You've already seen ViewExtensions. It defines nine methods that return Task<bool> and CancelAnimations. Seven of the nine methods target transform properties. The other two are FadeTo, which targets the Opacity property, and LayoutTo, which calls the Layout method.

Animation class

The Animation class has a constructor with five arguments to define callback and finished methods, and parameters of the animation.

Child animations can be added with Add, Insert, WithConcurrent, and overload of WithConcurrent.

The animation object is then started with a call to the Commit method.

AnimationExtensions class

The AnimationExtensions class contains mostly extension methods. There are several versions of an Animate method and the generic Animate method is so versatile that it's really the only animation function you need.

Working with the Animation class

The ConcurrentAnimations sample demonstrates the Animation class with several different animations.

Child animations

The ConcurrentAnimations sample also demonstrates child animations, which make use of the (very similar) Add and Insert methods.

Beyond the high-level animation methods

The ConcurrentAnimations sample also demonstrates how to perform animations that go beyond the properties targeted by the ViewExtensions methods. In one example, a series of periods get longer; in another example, a BackgroundColor property is animated.

More of your own awaitable methods

The TranslateTo method of ViewExtensions doesn't work with the Easing.SpringOut function. It stops when the easing output gets above 1.

The Xamarin.FormsBook.Toolkit library contains a MoreViewExtensions class with TranslateXTo and TranslateYTo extension methods that don't have this problem, as well as CancelTranslateXTo and CancelTranslateYTo methods for cancelling those animations.

The SpringSlidingEntrance demonstrates the TranslateXTo method.

The MoreExtensions class also contains a TranslateXYTo extension method that combines X and Y translation, and a CancelTranslateXYTo method.

Implementing a Bezier animation

It is also possible to develop an animation that moves an element along the path of a Bezier spline. The Xamarin.FormsBook.Toolkit library contains a BezierSpline structure that encapsulates a Bezier spline and a BezierTangent enumeration to control orientation.

The MoreViewExtensions class contains a BezierPathTo extension method and a CancelBezierPathTo method.

The BezierLoop sample demonstrates animating an element along a Beizer path.

Working with AnimationExtensions

One type of animation missing from the standard collection is a color animation. The problem is that there is no right way to interpolate between two Color values. It's possible to interpolate the individual RGB values, but just as valid is interpolating the HSL values.

For this reason, the MoreViewExtensions class in the Xamarin.FormsBook.Toolkit library contains two Color animation methods: RgbColorAnimation and HslColorAnimation. (There are also two cancellation methods: CancelRgbColorAnimation and CancelHslColorAnimation).

Both methods make use of ColorAnimation, which performs the animation by calling the extensive generic Animate method in AnimationExtensions.

The ColorAnimations sample demonstrates using these two types of color animations.

Structuring your animations

It's sometimes useful to express animations in XAML and use them in conjunction with MVVM. This is covered in the next chapter, Chapter 23. Triggers and Behaviors.