In this blog post I look at how to implement the fly-out fly-in effect seen in native Windows Phone 7 applications. This effect is seen in the native mail application; when you click on a message, the title flies out of the list then flies back in as the title of the message page.
This is the third in my "Metro In Motion" series where I am looking at how to re-create some of the stylish transitions and animations found in native Windows Phone 7 applications. As a Silverlight developer we have controls that adhere to the static Metro styling, but apart from Pivot and Panorama, the more dynamic features of the Metro style are something we have to come up with ourselves. So far previous posts have provided re-useable implementations for the fluid list animations between pivot pages and the 'peel' animation seen when applications exit. In this blog post I provide a simple re-useable implementation of the title fly-out and fly-in effect. This effect is not that easy to describe, so we'll let the following picture do the talking ...
Here is a video of this effect recorded on the emulator. This code has also been tested on a real device, and performs just fine.
Unfortunately because the animations are quite snappy, a YouTube video doesn't do them justice. Best viewed on a real phone!
Let's look at how this effect is implemented ...
Starting with the fly-out effect, the general principle is that when the user selects an item in the list, we handle some event in code behind. We must identify the on-screen element that flies off screen and animate its location using a storyboard, whilst fading everything else from view. When this animation has completed, we navigate to the next page. When the user returns to the same page, this element must be animated to return to its original location.
In order to make the code re-useable I have created a class which you present with the element to animate, it takes care of the fly-out effect, and then the fly-in which returns the UI to the original state.
Let's take a look at the code ...
Using This Effect
Firstly, we need to identify the elements which we wish to animate, so here we give them a name:
The page needs an instance of the class which manages this animation effect. When the ListBox raises its SelectionChanged event we use a bit of Linq-to-VisualTree to locate the element named above, then invoke ItemFlyOut, providing an 'action' which is called when the animation completes.
When the user navigates back to the page, you simple invoke ItemFlyIn, and this class takes care of animating the title element back into view:
This class also has a static method which can be used to animate the page title into view. With the page title named in XAML, it is as easy to use as this ...
So, this aptly named ItemFlyInAndOutAnimations does a good job of making this effect re-useable. Let's look under the covers to see how it works ...
How It Works
Probably the trickiest part of this effect for me was working out how to fade the page, via its opacity, without fading out the element being animated. The opacity property is inherited from an element to its children, therefore, if you set the opacity of the page, every element within it will have their opacity set also. To avoid this, the solution I came up with 'clones' the element that is being animated and places it in a popup, the popup also contains a full-screen rectangle which is used to fade-out the background.
The class which performs the animation constructs a Popup and a Canvas which is the popup's child element:
The fly-out animation creates a full-screen rectangle which masks everything on the screen, it then clones the visuals of the element being animated using a WriteableBitmap and places this in the popup also. A number of DoubleAnimations are constructed, one which animates the X location, one for the Y and one which animates the rectangle opacity to gradually fade-out the background. Note, the curved path that the animated element follows is achieved by using a EaseOut on the Y animation, and an EaseIn on the X:
Animating the element back into view is a little easier, here we remove the background mask and animate our cloned element back to its original location. Once the animation has completed we hide the popup and destroy our temporary visuals, and finally set the opacity of the original element back to '1.0' returning the UI to its original state: