Continuum Transition for Windows Phone Silverlight Toolkit
Posted on November 8th, 2011 by Benjii
You know that cool swooshing transition you get when you click an email on your Windows Phone? Now you too can make use of that awesome transition using only the Silverlight Toolkit and this handy dandy Continuum Transition class.
Step 1 – Go get the Silverlight Toolkit!!
As always, I suggest you use Nuget to include it, but feel free to download it from Codeplex
Step 2 – Let’s See How to Use It
The actual continuum transition class is pretty big for a blog post, so I’ll show you how to use it first and then you can copy the Continuum Transition class after that.
If you are already using the Silverlight Toolkit transitions using code, then this should hopefully be familar:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
var selectedElement = (sender as ListBox).ItemContainerGenerator.ContainerFromIndex(lstSeeding.SelectedIndex) as FrameworkElement;
var navOutTransition = new NavigationOutTransition();
navOutTransition.Forward = new ContinuumTransition(ContinuumTransitionMode.ContinuumForwardOutStoryboard, selectedElement);
var navInTransition = new NavigationInTransition();
navInTransition.Backward = new ContinuumTransition(ContinuumTransitionMode.ContinuumBackwardInStoryboard, selectedElement);
PhoneApplicationPage phoneApplicationPage =
(PhoneApplicationPage)(((PhoneApplicationFrame)Application.Current.RootVisual)).Content;
TransitionService.SetNavigationOutTransition(phoneApplicationPage, navOutTransition);
TransitionService.SetNavigationInTransition(phoneApplicationPage, navInTransition);
NavigationService.Navigate(new Uri("/DetailPage.xaml", UriKind.Relative));
}
I’ve used a listbox’s selection changed event as an example, as this is the most common scenario. To break it down, firstly we get the selected item’s framework element. This is the containing element that we are going to animate, in this case a list item.
Next, we setup the actual transitions using the awesome continuum transition class. The first parameter is the type of transition you are making and the second is the element you wish to animate.
After this, we obtain our phone application page and assign the transitions to the transition service.
Once we have done that we can navigate as per normal and the page will automatically transition for you!
Step 3 – Copy the Continuum Transition Class
The code in full is below. It is hosted on Github so you can be confident the below code is up to date.
Also please note the actual storyboards have come from the awesome guys at Clarity Consulting. There is an especially useful post about transitions you should go read right now.
namespace BenjiiMe.Animation{ public class ContinuumTransition : TransitionElement { public const string ContinuumElementPropertyName = "ContinuumElement"; public const string ContinuumModePropertyName = "Mode";
public FrameworkElement ContinuumElement { get { return (FrameworkElement)GetValue(ContinuumElementProperty); } set { SetValue(ContinuumElementProperty, value); } }
public ContinuumTransitionMode Mode { get { return (ContinuumTransitionMode)GetValue(ModeProperty); } set { SetValue(ModeProperty, value); } }
public static readonly DependencyProperty ContinuumElementProperty = DependencyProperty.Register(ContinuumElementPropertyName, typeof(FrameworkElement), typeof(ContinuumTransition), new PropertyMetadata(null));
public static readonly DependencyProperty ModeProperty = DependencyProperty.Register(ContinuumModePropertyName, typeof(ContinuumTransitionMode), typeof(ContinuumTransition), null);
public ContinuumTransition() { } public ContinuumTransition(ContinuumTransitionMode mode) { Mode = mode; } public ContinuumTransition(ContinuumTransitionMode mode, FrameworkElement element) { Mode = mode; ContinuumElement = element; }
public override ITransition GetTransition(UIElement element) { Storyboard storyboard = null; if (Mode == ContinuumTransitionMode.ContinuumBackwardInStoryboard) storyboard = XamlReader.Load(ContinuumBackwardInStoryboard) as Storyboard; else if (Mode == ContinuumTransitionMode.ContinuumBackwardOutStoryboard) storyboard = XamlReader.Load(ContinuumBackwardOutStoryboard) as Storyboard; else if (Mode == ContinuumTransitionMode.ContinuumForwardInStoryboard) storyboard = XamlReader.Load(ContinuumForwardInStoryboard) as Storyboard; else if (Mode == ContinuumTransitionMode.ContinuumForwardOutStoryboard) storyboard = XamlReader.Load(ContinuumForwardOutStoryboard) as Storyboard;
ContinuumElement.GetTransform<CompositeTransform>(TransformCreationMode.CreateOrAddAndIgnoreMatrix);
SetTargets(new Dictionary<string, FrameworkElement>() { { "LayoutRoot", element as FrameworkElement }, { ContinuumElementPropertyName, ContinuumElement } }, storyboard);
return new Transition(element, storyboard); }
public void SetTargets(Dictionary<string, FrameworkElement> targets, Storyboard sb) { foreach (var kvp in targets) { var timelines = sb.Children.Where(t => Storyboard.GetTargetName(t) == kvp.Key); foreach (Timeline t in timelines) Storyboard.SetTarget(t, kvp.Value); } }
internal static readonly string ContinuumForwardOutStoryboard = @"<Storyboard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""LayoutRoot""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""0""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""70""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseIn"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.Opacity)"" Storyboard.TargetName=""LayoutRoot""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""1""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseIn"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""ContinuumElement""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""0""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""73""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseIn"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateX)"" Storyboard.TargetName=""ContinuumElement""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""0""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""225""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseIn"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName=""ContinuumElement"" Storyboard.TargetProperty=""(UIElement.Opacity)""> <DiscreteDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0"" /> </DoubleAnimationUsingKeyFrames> </Storyboard>";
internal static readonly string ContinuumForwardInStoryboard = @"<Storyboard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""LayoutRoot""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""50""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""ContinuumElement""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""-70""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateX)"" Storyboard.TargetName=""ContinuumElement""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""130""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimation Storyboard.TargetProperty=""(UIElement.Opacity)"" From=""0"" To=""1"" Duration=""0:0:0.15"" Storyboard.TargetName=""LayoutRoot""> <DoubleAnimation.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""6""/> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard>";
internal static readonly string ContinuumBackwardOutStoryboard = @"<Storyboard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""LayoutRoot""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""0""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""50""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseIn"" Exponent=""6""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimation Storyboard.TargetProperty=""(UIElement.Opacity)"" From=""1"" To=""0"" Duration=""0:0:0.15"" Storyboard.TargetName=""LayoutRoot""> <DoubleAnimation.EasingFunction> <ExponentialEase EasingMode=""EaseIn"" Exponent=""6""/> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard>";
internal static readonly string ContinuumBackwardInStoryboard = @"<Storyboard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateX)"" Storyboard.TargetName=""ContinuumElement""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""-70""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""ContinuumElement""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""-30""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""0""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""3""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName=""ContinuumElement"" Storyboard.TargetProperty=""(UIElement.Opacity)""> <DiscreteDoubleKeyFrame KeyTime=""0:0:0"" Value=""1"" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=""(UIElement.Opacity)"" Storyboard.TargetName=""LayoutRoot""> <EasingDoubleKeyFrame KeyTime=""0"" Value=""0""/> <EasingDoubleKeyFrame KeyTime=""0:0:0.15"" Value=""1""> <EasingDoubleKeyFrame.EasingFunction> <ExponentialEase EasingMode=""EaseOut"" Exponent=""6""/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimation Duration=""0"" To=""0"" Storyboard.TargetProperty=""(UIElement.RenderTransform).(CompositeTransform.TranslateY)"" Storyboard.TargetName=""LayoutRoot""/> </Storyboard>"; }
public enum ContinuumTransitionMode { ContinuumForwardOutStoryboard, ContinuumForwardInStoryboard, ContinuumBackwardOutStoryboard, ContinuumBackwardInStoryboard }}
Welcome to the bottom of the post, please spread the word about this transition to better the Windows Phone platform for everyone