It's always been tedious in XAML apps to make transitional animations between two pages.
To animate an image between two pages, the navigation system had to be modified to allow these animations.
The anniversary update brings a new medium called connected animations” that makes these animations trivial to make.
Original illustration unavailable: connectedanimation
How does this work?
The ConnectedAnimationService class allows a visual element to be passed between multiple XAML pages.
Let's code together an example to understand how this works.
Master page:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<GridView x:Name="ItemsGridView"
Loaded="ItemsGridView_Loaded"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="ItemsGridView_ItemClick"
Margin="50"
ItemsSource="{x:Bind ViewModel.Items}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Thumbnail">
<Border BorderBrush="Black"
BorderThickness="1">
<Image x:Name="ImageItem"
Width="200"
Height="200"
Margin="2"
Stretch="Uniform"
Source="{x:Bind ImageUrl}" />
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
private void ItemsGridView_ItemClick(object sender, ItemClickEventArgs e)
{
var container = ItemsGridView.ContainerFromItem(e.ClickedItem) as GridViewItem;
if (container != null)
{
var root = (FrameworkElement)container.ContentTemplateRoot;
//Au click sur la gridView
//Récupération de l'image que l'on veut animer.
var image = (UIElement)root.FindName("ImageItem");
//On prépare l'animation
ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("Image", image);
}
var item = (Thumbnail)e.ClickedItem;
//On navigue vers la page détail : en passant en paramètre l'url de l'image selectionnée
Frame.Navigate(typeof(ConnectedAnimationDetail), _navigatedUri = item.ImageUrl);
}
Details page:
The code XAML:
<Page x:Class="UWPWhatsNew.Views.ConnectedAnimation.ConnectedAnimationDetail"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPWhatsNew.Views.ConnectedAnimation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Image x:Name="_image"
Margin="50"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Grid>
</Page>
C# code
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e)
//Récupération du paramètre passé lors de la navigation
_image.Source = new BitmapImage(new Uri((string)e.Parameter));
//On récupére l'animation ayant comme nom Image.
var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation("Image");
if (animation != null)
{
_image.Opacity = 0;
//On lance l'animation uniquement quand l'image est chargée
_image.ImageOpened += (sender_, e_) =>
{
animation.TryStart(_image);
};
}
//On s'abonne à l'évènement back de la page, comme ça l'utilisateur clickera sur back on rejouera l'animation dans l'autre sens
_systemNavigationManager.BackRequested += ConnectedAnimationDetail_BackRequested;
_systemNavigationManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
}
When the user clicks back the animation is prepared so that the master page can play the animation.
private void ConnectedAnimationDetail_BackRequested(object sender, BackRequestedEventArgs e)
{
if (e.Handled)
{
return;
}
ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("Image", _image);
e.Handled = true;
Frame.GoBack();
}
Back to the main page:
The visual element to be animated is retrieved and reverse animation is launched.
private void ItemsGridView_Loaded(object sender, RoutedEventArgs e)
{
if (_navigatedUri != null)
{
//récupération de l'animation
var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation("Image");
if (animation != null)
{
var item = ViewModel.Items.Where(compare => compare.ImageUrl == _navigatedUri).First();
//on scroll vers l'item
ItemsGridView.ScrollIntoView(item, ScrollIntoViewAlignment.Default);
ItemsGridView.UpdateLayout();
var container = ItemsGridView.ContainerFromItem(item) as GridViewItem;
if (container != null)
{
var root = (FrameworkElement)container.ContentTemplateRoot;
var image = (Image)root.FindName("ImageItem");
image.Opacity = 1;
//on lance l'animation
animation.TryStart(image);
}
else
{
animation.Cancel();
}
}
_navigatedUri = null;
}
}
Do I have to wait until all my clients have installed Windows 10 Anniversary to add conneconnected animations”?
No, you can now add updates to the Anniversary Update. But before using the ConnectedAnimationService class you will need to check that your client has the API.
private bool HaveConnectedAnimationService()
{
return ApiInformation.IsTypePresent("Windows.UI.Xaml.Media.Animation.ConnectedAnimationService");
}
//Vérification que l'API est présente.
if(HaveConnectedAnimationService())
{
var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation("Image");
...
}