Part 22: Animating the Reel Grid with a Storyboard
Description
Source Code: https://aka.ms/absbeginnerdevwp8
PDF Version: https://aka.ms/absbeginnerdevwp8pdf
The final step will be fun ... we'll animate the reel object on our record audio screen. We want it to rotate as we're recording ... that's a nice visualization of what the app is doing, a nice visual cue to the user that they are in the middle of an important operation with the app.
Our game plan in this lesson:
- We'll create a Storyboard that includes an animation to rotate the Ellipse and the other objects.
- We'll programmatically start and stop the animation
... but first we'll need to learn a little about creating animations on the Windows Phone.
1. Declaratively define the animation
Before we dive too deeply into the topic of animation, I want to discuss it at a high level. Once we're comfortable with how animation works in XAML UI frameworks, we'll have a bit more confidence to apply a specific animation to rotate our reel.
First, its important to realize that XAML controls like the Grid, Button, etc. are defined separately from animation definitions. You can create an animation that is applied to different controls as needed. An animation is associated with a control and then triggered by some event. In our case, we've already defined the Grid and the shapes that will comprise the reel. We'll soon define an animation and associate the two, then we'll write C# code to trigger the animation. Again, we'll do all of this before the end of this lesson.
Animations are made up of a Storyboard object and at least one Animation object.
Let's start with the Animation. First, there are several different types of animation data types. We're using a DoubleAnimation data type because we want to move a property (the Rotation property) from 0.0 to 360.0—the angle of the animation every 4 seconds. In other words, we want the Grid to rotate every 4 seconds. Besides the DoubleAnimation, there's also a ColorAnimation class for animating between two colors, and a PointAnimation for modifying an objects X Y coordinate or its size.
An Animation is basically a timeline combined with a result. The results are determined by the specific Animation class you pick like we just talked about. It's important to know that all Animation classes inherit from a Timeline class which confers properties related to timing of the animation ... the Begin time, allowing you to delay the start of animation, perhaps waiting for other animations on the storyboard to begin or complete, a Duration property that effects how long the animation should take before delivering the desired result—how long should it take for our fade-in effect, in this case. There are also AutoReverse and RepeatBehavior properties, which do what they suggest.
A Storyboard is a collection of one or more Animations. You group the Animations you want triggered by a specific event such as a button click, a loaded event, and so on. The Storyboard allows you to pair an Animation with a target object. The animation is just a definition of what property should be affected, when it should be affected and how long. We have to APPLY that Animation to a target object. In our case, that target object will be the Grid that contains our shapes representing the reel.
Our Storyboard will be simple since we just want one thing to happen—a rotation from 0 to 360 degrees every 4 seconds. Once we're ready to allow the Storyboard to play, we call its Begin() method. It will in turn kick off all it's child Animations and child Storyboards.
There are 4 possible transforms that you can animate as listed and diagrammed on this page:
https://msdn.microsoft.com/en-us/library/ms750596.aspx
(I realize that this article is specifically for WPF, but many of the concepts transfer to the Windows Phone API.)
- RotateTransform
- ScaleTransform
- SkewTransform
- TranslateTransform
... as well as other attributes you can change with the ColorAnimation and the like. There's a lot more to learn about animations, and for a more complete explanation of animations, I recommend you start here:
https://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206955(v=vs.105).aspx
Now that you have the basics of StoryBoards and Animations, let's modify the Grid containing the shapes that comprise the reel graphic. You'll recall that the large ellipse and the smaller rectangles and ellipse are all contained in a Grid for layout purposes.
To get them to all move correctly at the same time, it is easier to just animate / rotate the grid (rather than each individual shape):
I'll add a name so I can access it programmatically, and I want to indicate that I want to entire grid and all its children to animate together, as a group, or rather as a composite:
- Add the programmatic name attribute.
- I set the RenderTransform property to CompositeTransform. Essentially, what I'm saying is that I will transform the contents of the Grid as one complete unit. I've not provided the details of HOW I'll transform the grid, just the fact that, for the purpose of performing transformations on the Grid, I want to treat the Grid and its children as a group. I'll define HOW I'll transform the grid in a Storyboard.
Near the top of the RecordAudio.xaml page (beneath the PhoneApplicationPage declaration), I will add a Resources section:
- We're creating a Page-level resource.
- We're creating a Storyboard ... because it's Page-level, we could re-use this in other spots in our page. We'll give the Storyboard a name, "RotateCircle" and once it starts, it's repeat behavior should be "Forever". We'll control start and stop programmatically. I'll access this Storyboard programmatically by it's name in a moment to start / stop it.
- We'll build a DoubleAnimation object. Why DoubleAnimation? As we discussed at the outset, we want to modify the Rotation property (see the Storyboard.Target property) from 0.0 to 360.0, which are numerical (and therefore will require we use the DoubleAnimation). We set the duration of the animation to 4 seconds and so, in 4 seconds, we want to increase the Rotation value starting at 0 and increasing to 360. We set the TargetName, which is the name we gave the Grid containing our reel. The TargetProperty is tricky ... we have to write it this way due to the fact that we're working with a CompositeTransform ... as I mentioned a moment ago, we want to animate the Grid AND ITS CHILDREN. Otherwise, we could simply set the TargetProperty="Rotation".
2. Programmatically start and stop the animation
What comes next is easy now that we've declaratively defined the animation. We'll start and stop the animation based on the state of the ToggleButton:
- While recording, start the animation.
- When finished recording, stop the animation.
If we were to run the application at this point, we would notice an odd behavior while recording:
The reel is not rotating in place, but rather, it is rotating around the page. This is because we didn't define the spot of origin for the transform to take place. Instead of at its default X Y position (0, 0 ... upper left-had corner), we want it to be in the middle (.5, .5), so we'll set the RenderTransformOrigin to that position:
Now when we re-run the app, the reel spins instead of traveling:
3. Deploy to physical Phone Device
Just for fun, I wanted to see this working on my Nokia Lumia 920, so I connected my device to my computer with a USB cable and used the drop-down next to the Run button on the toolbar to select Device:
I was able to run the app, record and save sounds, even hit break points just like I could using the Emulator in Visual Studio. Excellent.
Recap
To recap, in this lesson we learned about animation using Storyboard and the relation to Animation classes. We talked about the different types of animations and transforms you can add to your app. Then, we learned how to programmatically trigger the storyboard and how to stop it. We learned about things like how to modify the rotation animation's starting point by changing RenderTransformOrigin attribute. The big takeaway is that if you can imagine it, there's likely a way to accomplish it given the wealth of animation options in XAML and the Windows Phone API.
Now that we've finished our first version of this