This blog post is part #2 of my Metro In Motion series. In this post I demonstrate how to implement the animated 'peel' effect seen when native Windows Phone 7 applications exit.
In my previous blog post I discussed how the Metro Design Language that heavily influences the Windows Phone 7 style is not just about static graphics, it is also about fluid transitions. In that post I demonstrated a technique for making items within lists slide gracefully as the user moves between pivot pages. The post was pretty popular, so I have decided to turn it into a series, looking at how to implement the various fluid animations that are present in Windows Phone 7 native applications.
A feature found in most native Windows Phone 7 applications is the 'peel' effect where when the application is exited, the various components peel away from the top of the screen to the bottom. You can see my implementation of this effect in action in the video below. You might have to watch it a few times, the animation comes right at the end as is over pretty quickly!
The implementation of this effect has to be pretty generic - each application user interface is different, and for the peel effect to be useable, it cannot be tightly coupled to a specific UI layout.
The approach I have come up with is to define an extension method that can be applied to a list of
FrameworkElements. This method creates a suitable
Storyboard for each element and fires them in order. An Action is invoked when the last animation completes (more on that later!):
The peel animation itself works by associating a
PlaneProjection with each element and animating its rotation and offset properties:
Thanks to the genius Charles Petzold for explaining to me how PlaneProjections work! rotating an element around any point other than its centre is not quite as easy as it might seem!
As an aside, I would love to come up with an animation that more closely matches the native applications. I think what I have come up with is close, but noticeably different. If anyone is up for a challenge, please have a go at tweaking this animation and let me know what you come up with!
The above code gives us all we need in order to peel our UI, however, we now need to work out how to apply this in practice. Using the application developed in the previous post, we can see that the UI is composed of three discrete parts, the title, the pivot header and the list which resides within the currently visible pivot-item:
We'll start with the trickiest part -the list. In my previous blog post I showed how it was possible to enumerate all the items which are currently visible within a
ItemsControl). To make this code more re-useable I have refactored it as an extension method on ItemsControl:
When the back button is pressed, we can locate the list which is located in the visible pivot-item, using Linq-to-VisualTree, and use the extension method above to extract its visible items:
By inspecting the
Pivot control's template, we can see that the header is named "HeadersListElement", making it easy to locate using Linq again:
Finally, the small text which indicates the name of the application is a named element in the XAML markup, so we already have a reference to this one. Putting all the above together, with a simple Linq
Union, gives the following:
The final twist is that when the back 'key' is pressed the application exits immediately. To avoid this, we cancel the event. However, we need a way to exit the application when the animation has finished. Unfortunately Silverlight for WP7 does not have a mechanism for programatically exiting! This has been the subject of much debate. I opted for the popular throw-an-unhandled-exception route. Yes it is ugly, no, I do not like it, but let's not get distracted. The 'peel' effect is now done!
To use this code in your own application, you will have to assemble your own list of elements based on your UI, however, this does give a lot of flexibility.
You can download the project sourcecode here: MetroInMotion2.zip