SDK Anniversary : les connected animations
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 triviales à réaliser.
Comment ça fonctionne ?
La classe ConnectedAnimationService permet de passer un élément visuel entre plusieurs pages XAML.
Nous allons coder ensemble un exemple pour comprendre comment cela fonctionne.
Page maître:
La partie XAML :
<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>
Dans le code C# nous utiliserons l'animation avec l'objet visuel à animer :
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 :
Dans la page de détail, nous recevrons l'image à animer :
<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>
Dans le code C# nous recevrons l'image à animer et nous lançons l'animation :
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 clique 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:
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; } }
Et si tous mes clients ne sont pas sur anniversary update?
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 a 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"); ... }
Pour aller plus loin
Lien vers la doc officielle
Vidéo de BUILD montrant les connected animations
Lien vers le GitHub de démo de MS
Happy coding :)
Commentaires