Il a toujours été fastidieux dans les apps XAML de faire des animations de transition entre deux pages.
Pour animer une image entre deux pages, il fallait modifier le système de navigation pour permettre ces animations.
L’anniversary update apporte un nouveau moyen appelé les “connected animations” qui rend ces animations triviale à réaliser.
Illustration d’origine indisponible : connectedanimation
Comment ça fonctionne ?
La classe ConnectedAnimationService permet de passer un élément visuel entre plusieurs page XAML.
Nous allons coder ensemble un exemple pour comprendre comment cela fonctionne.
Page maître:
<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);
}
Page de détail :
Le 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>
Le code C#
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;
}
Lorsque l’utilisateur click sur back on prépare l’animation pour que la page maître puisse jouer l’animation.
private void ConnectedAnimationDetail_BackRequested(object sender, BackRequestedEventArgs e)
{
if (e.Handled)
{
return;
}
ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("Image", _image);
e.Handled = true;
Frame.GoBack();
}
Au retour sur la page maître:
On récupère l’élément visuel à animer et lance l’animation inverse.
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;
}
}
Dois-je attendre que tous mes clients aient installé Windows 10 Anniversary pour ajouter des “connected animations”?
Non, vous pouvez dès à présent ajouter des nouveautés d’anniversary Update. Mais avant d’utiliser la classe ConnectedAnimationService il faudra vérifier si votre client à bien l’API présente. Ci dessous le code vérification :
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");
...
}