Build this app using Fluent Design

Windows Developer
Windows Developer
Published in
14 min readApr 6, 2018

Microsoft’s Fluent Design System enables developers to create modern, clean user experiences incorporating light, depth, motion, material and scale. It’s the new standard for UI design and user interactions on Windows, and it’s very simple to implement.

To get you up to speed, we’ll show you how to create an example app using many of the guidelines found in the Fluent Design System. The app will take advantage of components from the UWP Community Toolkit, which is an excellent source of additional code examples, custom controls, helper functions and other services.

We’ll walk though Fluent Design aspects of the application development process and reference code and classes that reside here, but will only examine code directly related to the Fluent Design features we are demonstrating.

By the end of the exercise, you’ll have seen how Fluent design works in practice, understand the principles behind the interactions it includes and, if you follow along, you’ll create an app which looks clean, modern and ready for use:

Our sample app is a movie listing app, letting users see cinema releases in the current month and view information about popular and highly rated movies from the past year.

To obtain basic movie information, we’ll query the free service The Movie DB API (TMDb). This is a free service, but does require a private developer API Key that you will need to request before you can build this app.

Prerequisites

  • Windows 10, upgraded to the Fall Creators Update (or later)
  • Visual Studio 2017 installed, with the Universal Windows Platform Development Workload
  • A TMDb developer API key

Step 1: Create the application.

Starting from scratch, create a brand new blank Universal Windows App.

  • Open Visual Studio 2017
  • Choose File -> New -> Project from the main menu
  • Select Windows Universal from the left navigation pane
  • Select Blank App (Universal Windows) from the right pane
  • Enter the “DiscoverMovieSample” in the Name field
  • Enter a Location, or keep the default
  • Select the OK button

Step 2: Select target and minimum platform version.

Set the target and minimum platform versions to the Windows 10 Fall Creators Update to support the latest Fluent Design System additions and controls.

  • Ensure the Target version is set to Windows 10 Fall Creators Update (10.0; Build 16299)
  • Set the Minimum version to Windows 10 Fall Creators Update (10.0; Build 16299)

Step 3: Add project dependencies.

Use NuGet packages to help facilitate development. The Microsoft.Toolkit.* packages and the Win2D.uwp package are related to some of the Fluent Design techniques used later in the walkthrough. The others will help simplify other general tasks.

  • Choose Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution… from the main menu
    - or -
  • Right-Click on Project in Solution Explorer and choose Manage NuGet Packages…
  • Ensure that the Microsoft.NETCore.UniversalWindowsPlatform package has been installed by default.
  • Add the following packages:

Microsoft.Extensions.Configuration

Microsoft.Extensions.Configuration.Binder

Microsoft.Extensions.Configuraion.Json

Microsoft.Toolkit.Uwp.UI

Microsoft.Toolkit.Uwp.UI.Animations

Microsoft.Toolkit.Uwp.UI.Controls

Newtonsoft.Json

Win2D.uwp

Step 4: Extend Acrylic into the title bar.

One of the more noticeable additions to the Fluent Design System is the Acrylic material. At a basic level, Acrylic is a semi-transparent, semi-textured background that provides a sense of light, texture and depth to applications.

Simply use one of a variety of new ThemeResource brushes (or create a custom one) to add Acrylic to you apps using pure Xaml markup. Extending the Acrylic material into the app’s toolbar, however, does require a tiny bit of code:

  • Edit App.xaml.cs and add the following code:
private void ExtendAcrylicIntoTitleBar(){CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;var titleBar = ApplicationView.GetForCurrentView().TitleBar;titleBar.ButtonBackgroundColor = Colors.Transparent;titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;}
  • In the OnLauched event handler, add at the end of the method:
protected override void OnLaunched(LaunchActivatedEventArgs e){this.ExtendAcrylicIntoTitleBar();}

Step 5: Create the main page view.

By default, Visual Studio 2017 should have created a MainPage.xaml file for you. If not, simply add a new page yourself. Note, this walkthrough assumes the specified background image, main-background.jpg, exists in the project’s Assets folder. You can download it here, or use one of your own images.

By default, Visual Studio 2017 should have created a MainPage.xaml file for you. If not, simply add a new page yourself. Note, this walkthrough assumes the specified background image, main-background.jpg, exists in the project’s Assets folder. You can download it here, or use one of your own images.

  • Edit the MainPage.xaml file
  • Add the following namespace the Page control’s namespaces:
xmlns:appmodel=”using:Windows.ApplicationModel”
  • Change the Grid element as follows to use an Acrylic brush for the background:
<Grid Background=”{ThemeResource SystemControlChromeMediumAcrylicWindowMediumBrush}”>
  • Add a NavigationView element with several NavigationViewItem elements to the Grid to provide a mechanism to navigate to other areas of the app.
<NavigationView x:Name=”MainContent”AlwaysShowHeader=”False”IsSettingsVisible=”False”SelectionChanged=”OnSelectionChanged”><NavigationView.MenuItems><NavigationViewItem Content=”Home” Tag=”home”><NavigationViewItem.Icon><FontIcon Glyph=”&#xE10F;”/></NavigationViewItem.Icon></NavigationViewItem><NavigationViewItemSeparator/><NavigationViewItem Content=”What’s playing now?” Tag=”movies_now” ><NavigationViewItem.Icon><FontIcon Glyph=”&#xE8B2;” /></NavigationViewItem.Icon></NavigationViewItem><NavigationViewItem Content=”Opening this month” Tag=”movies_month” ><NavigationViewItem.Icon><FontIcon Glyph=”&#xE8B2;” /></NavigationViewItem.Icon></NavigationViewItem><NavigationViewItem Content=”Most popular last year” Tag=”movies_popular”><NavigationViewItem.Icon><FontIcon Glyph=”&#xE8B2;” /></NavigationViewItem.Icon></NavigationViewItem><NavigationViewItem Content=”Highest rated last year” Tag=”movies_rated”><NavigationViewItem.Icon><FontIcon Glyph=”&#xE8B2;” /></NavigationViewItem.Icon></NavigationViewItem></NavigationView.MenuItems><Frame x:Name=”ContentFrame”><Frame.Background><ImageBrush ImageSource=”Assets/main-background.jpg”/></Frame.Background><Frame.ContentTransitions><TransitionCollection><NavigationThemeTransition /></TransitionCollection></Frame.ContentTransitions></Frame></NavigationView>
  • Add another Grid element after the NavigationView to contain a custom title bar. Since we’ve extended the Acrylic material into the system title bar, we’ll have to provide our own.
<Grid x:Name=”AppTitleBar” Background=”Transparent” VerticalAlignment=”Top” ><! — Width of the padding column is set in LayoutMetricsChanged handler. →<! — Using a padding column instead of Margin ensures that the background paints →<! — the area under the caption control buttons (for transparent buttons). →<Grid.ColumnDefinitions><ColumnDefinition x:Name=”LeftPaddingColumn” Width=”0"/><ColumnDefinition/></Grid.ColumnDefinitions><! — Adds a gradient tint so the app back button can be seen on light backgrounds. →<Rectangle x:Name=”BackButtonBackground”Grid.Column=”0"Grid.ColumnSpan=”2"Visibility=”Collapsed”><Rectangle.Fill><LinearGradientBrush EndPoint=”1,1" StartPoint=”0,0"><GradientStop Color=”#3F000000"/><GradientStop Color=”Transparent” Offset=”0.2"/></LinearGradientBrush></Rectangle.Fill></Rectangle><TextBlock Text=”{x:Bind appmodel:Package.Current.DisplayName}”Grid.Column=”1"Style=”{StaticResource CaptionTextBlockStyle}”Margin=”8,8,0,0"/></Grid>

Step 6: Implement a custom title bar.

With the custom title bar Xaml defined in the previous step, little bit of additional code is needed for the title bar to display properly:

  • Edit the MainPage.xaml.cs file.
  • Add the following code to the MainPage class constructor:
this.InitializeComponent();// Use custom title bar.var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;this.UpdateTitleBarLayout(coreTitleBar);Window.Current.SetTitleBar(this.AppTitleBar);coreTitleBar.LayoutMetricsChanged += (s, a) => UpdateTitleBarLayout(s);
  • Add the method used in the event hander for the LayoutMetricsChanged event:
private void UpdateTitleBarLayout(CoreApplicationViewTitleBar coreTitleBar){// Get the size of the caption controls area and back button// (returned in logical pixels), and move your content around as necessary.var isVisible = SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility == AppViewBackButtonVisibility.Visible;var width = isVisible ? coreTitleBar.SystemOverlayLeftInset : 0;LeftPaddingColumn.Width = new GridLength(width);// Update title bar control size as needed to account for system size changes.this.AppTitleBar.Height = coreTitleBar.Height;}

Step 7: Add additional content pages.

Now, create the three additional pages needed later to serve as placeholders so Visual Studio doesn’t complain when we reference them. (We’ll come back to them later to add content and functionality.)

  • Add a new blank page named “WelcomePage” to the project.
  • Add a new blank page named “MovieListPage” to the project.
  • Add a new blank page named “MovieDetailPage” to the project.

Step 8: Add navigation to the main page.

Now that the major pages are in place, we can wire up the navigation functionality by implementing some logic for the NavigationView control and adding support for the system back button.

  • Edit the MainPage.xaml.cs file.
  • In the class constructor, add support for the system back button (which does not appear by default):
// Use system back button to navigate back between content pages.SystemNavigationManager.GetForCurrentView().BackRequested += MainPage_BackRequested;this.ContentFrame.Navigated += ContentFrame_Navigated;// Navigate to WelcomePage on Load.this.Loaded += MainPage_Loaded;
  • Add the following new method to make the system back button visible when there are pages to go back to. Also, since we extended Acrylic into the title bar, the back button may not be visible on lightly-colored backgrounds. For this example, we are also updating the BackButtonBackground element from Step 6 to improve visibility:
private void UpdateAppBackButton(){var backButtonVisibility = this.ContentFrame.CanGoBack ?AppViewBackButtonVisibility.Visible :AppViewBackButtonVisibility.Collapsed;var backgroundVisibility = backButtonVisibility == AppViewBackButtonVisibility.Visible ?Visibility.Visible :Visibility.Collapsed;var snm = SystemNavigationManager.GetForCurrentView();snm.AppViewBackButtonVisibility = backButtonVisibility;this.BackButtonBackground.Visibility = backgroundVisibility;}
  • Add an event handler for the Navigated event of the content Frame, so that whenever a navigation activity occurs, the visibility of the back button is properly updated:
private void ContentFrame_Navigated(object sender, NavigationEventArgs e){this.UpdateAppBackButton();}
  • Add an event handler for the Loaded event of the Page to ensure the first item in the NavigationView menu is selected by default:
private void MainPage_Loaded(object sender, RoutedEventArgs e){this.MainContent.SelectedItem = this.MainContent.MenuItems.First();}
  • Handle the NavigationView control’s SelectionChanged event to navigate to the page whenever a menu item in the NavigationView is selected (typically by user interaction). The code that clears the navigation stack when the user returns to the home page is strictly a design decision:
private void OnSelectionChanged(NavigationView sender,NavigationViewSelectionChangedEventArgs args){var item = args.SelectedItem as NavigationViewItem;var tag = item.Tag.ToString();if (tag.ToLowerInvariant().Equals(“home”)){ContentFrame.Navigate(typeof(WelcomePage));ContentFrame.BackStack.Clear();this.UpdateAppBackButton();return;}ContentFrame.Navigate(typeof(MovieListPage), tag);}

Step 9: Create the welcome page.

The welcome page will serve as the app’s home page and the destination of the first menu item in the NavigationView element from Step 5.

  • Edit the WelcomePage.xaml file and replace the default Grid element with the following static content:
<Grid Background=”Transparent”><StackPanel HorizontalAlignment=”Center” VerticalAlignment=”Center”><TextBlock Text=”Welcome to What’s Playing?”TextWrapping=”WrapWholeWords”TextAlignment=”Center”FontSize=”48"FontStyle=”Italic”></TextBlock><TextBlock Text=”a sample application demonstrating the Fluent Design System”Margin=”0 20 0 0"TextWrapping=”WrapWholeWords”TextAlignment=”Center”FontSize=”24"FontStyle=”Italic”/></StackPanel></Grid>

There is no additional work needed for the Welcome page.

Step 1 0: Create the movie list page.

The MovieListPage will display a condensed list of movies depending upon the user’s choice from the main menu in the NavigationView. In Step 5, we provided four options for the user: show currently playing movies, movies released in the current month, popular movies last year and highly-rated movies last year. Since the display for all these options is similar, the MovieListPage can be re-used for all of them.

  • Use a GridView element to display the list of movies, so edit the MoveListPage.xaml and add the following Xaml to the default Grid element:
<GridView x:Name=”MovieGridView”Margin=”10, 40, 10, 10"ItemsSource=”{Binding Movies}”IsItemClickEnabled=”True”SelectionMode=”None”ItemClick=”MovieGridView_ItemClick”></GridView>

The margin is specified on the GridView element to ensure that the movie elements do not overlap the title bar. Additionally, IsItemClickEnabled attribute is set to True to enable the ItemClick event. SelectionMode is set to None since we are not interested in the selected item for this implementation.

  • Add some default transitions to the GridView for the items, by adding the following Xaml to the GridView element.
<GridView.ItemContainerTransitions><TransitionCollection><EntranceThemeTransition IsStaggeringEnabled=”True”/><RepositionThemeTransition /></TransitionCollection></GridView.ItemContainerTransitions>

These default transitions will add some fluid animations when items are added to the GridView or repositioned due to window or container resizing. As animations go, you can’t get any easier than that.

  • Add a DataTemplate to display the individual movies by adding the following Xaml to the GridView element:
<GridView.ItemTemplate><DataTemplate><Border Margin=”5" Width=”375" Background=”#CCFFFFFF”><Grid><Grid.ColumnDefinitions><ColumnDefinition Width=”96" /><ColumnDefinition Width=”*” /></Grid.ColumnDefinitions><Image x:Name=”PosterImage” Grid.Column=”0" MinWidth=”96" MinHeight=”144"><Image.Source><BitmapImage UriSource=”{Binding PosterPath}”/></Image.Source></Image><Grid Grid.Column=”1" Margin=”10"><Grid.RowDefinitions><RowDefinition Height=”Auto” /><RowDefinition Height=”*” /></Grid.RowDefinitions><StackPanel Grid.Row=”0"><TextBlock Text=”{Binding Title}”FontSize=”18" TextWrapping=”WrapWholeWords”/><Grid><Grid.ColumnDefinitions><ColumnDefinition Width=”1*” /><ColumnDefinition Width=”2*” /></Grid.ColumnDefinitions><StackPanel Grid.Column=”0" Orientation=”Horizontal”><FontIcon Glyph=”&#xE787;”FontSize=”12"Opacity=”0.5"Margin=”0,0,5,0"/<TextBlock FontSize=”11"HorizontalAlignment=”Left”VerticalAlignment=”Center”Text=”{Binding FormattedReleaseDate}” /></StackPanel><TextBlock Grid.Column=”1"Text=”{Binding DeliminatedGenres}”FontSize=”11"HorizontalAlignment=”Right”VerticalAlignment=”Center”TextWrapping=”NoWrap”TextTrimming=”CharacterEllipsis” /></Grid></StackPanel><Grid Grid.Row=”1" VerticalAlignment=”Bottom”><Grid.ColumnDefinitions><ColumnDefinition Width=”2*” /><ColumnDefinition Width=”1*” /></Grid.ColumnDefinitions><StackPanel Grid.Column=”0" Orientation=”Vertical”><TextBlock FontSize=”10">user rating</TextBlock><RatingControl IsReadOnly=”True”HorizontalAlignment=”Left”Value=”{Binding FiveStarVotingAverage}”InitialSetValue=”0"Caption=”{Binding RatingCaption}”></RatingControl></StackPanel></Grid></Grid></Grid></Border></DataTemplate></GridView.ItemTemplate>

Note the Image element named “PosterImage” used to display the movie’s poster image — this element will become important for tying the MovieListPage and the MovieDetailPage together.

  • To load the GridView with movies, edit the MovieListPage.xaml.cs file and add the following method override code:
private MovieListViewModel _vm;public MovieListPage(){this.InitializeComponent();_vm = new MovieListViewModel();this.DataContext = _vm;}protected async override void OnNavigatedTo(NavigationEventArgs e){base.OnNavigatedTo(e);var tag = e.Parameter as string;await _vm.LoadMoviesAsync(tag);}

This code relies on the MovieListViewModel class to provide the list of movies and other functionality. You can download this file here.

Step 1 1: Create the movie detail page.

The MovieDetailPage will display a single movie and some additional information not found on the MovieListPage. In later steps, we’ll add a Parallax effect to the background as well as a custom composite effect to soften the image.

  • Edit the MovieDetailPage.xaml file and add the following namespace to the Page element:
xmlns:toolkit=”using:Microsoft.Toolkit.Uwp.UI.Controls”
  • Add the following style definition directly to the Page element:
<Page.Resources><Style x:Key=”BorderedPanel” TargetType=”Border”><Setter Property=”Background” Value=”#16FFFFFF” /><Setter Property=”BorderBrush” Value=”#32FFFFFF” /><Setter Property=”BorderThickness” Value=”1" /><Setter Property=”Padding” Value=”10" /><Setter Property=”Margin” Value=”0 10 0 30" /></Style><Style x:Key=”FactLabel” TargetType=”TextBlock”><Setter Property=”FontSize” Value=”18" /><Setter Property=”FontWeight” Value=”Bold” /><Setter Property=”Margin” Value=”0 20 0 0"/></Style></Page.Resources>
  • Replace the Grid element with the following Xaml:
<Grid DataContext=”{Binding Movie}”><Grid><Grid.ColumnDefinitions><ColumnDefinition Width=”2*” /><ColumnDefinition Width=”3*” /></Grid.ColumnDefinitions><StackPanel Grid.Column=”0" Margin=”40" HorizontalAlignment=”Stretch”><Image x:Name=”PosterImage”Stretch=”Uniform”MaxWidth=”400"HorizontalAlignment=”Left”VerticalAlignment=”Top”Source=”{Binding PosterImage}” /><TextBlock Text=”{Binding Tagline}”Margin=”0 10 0 0"FontSize=”24"FontStyle=”Italic”HorizontalAlignment=”Center”TextAlignment=”Center”TextWrapping=”WrapWholeWords”/></StackPanel><ScrollViewer Grid.Column=”1"x:Name=”MovieDetails”Margin=”0 40 00 0"VerticalScrollBarVisibility=”Visible”><Grid Margin=”20 0 40 0"><Grid.RowDefinitions><RowDefinition Height=”Auto”/><RowDefinition Height=”Auto”/><RowDefinition Height=”*”/></Grid.RowDefinitions><StackPanel Grid.Row=”0" Margin=”0 0 0 30"><TextBlock Text=”{Binding Title}”FontSize=”38"FontWeight=”Bold”TextWrapping=”Wrap” /><TextBlock Text=”{Binding ReleaseDateYear}”FontSize=”24" /></StackPanel><Border Grid.Row=”1" Style=”{StaticResource BorderedPanel}”><StackPanel Orientation=”Horizontal” ><toolkit:RadialGauge Minimum=”0"Maximum=”100"ScaleWidth=”40"Height=”100"Width=”100"TickLength=”0"TickSpacing=”10"TickBrush=”Gainsboro”ScaleTickBrush=”White”ScaleTickWidth=”3"NeedleWidth=”0"ValueBrush=”Black”Value=”{Binding VotingAverageAsPercent}” /><TextBlock Text=”User Rating”FontWeight=”Bold”FontSize=”24"VerticalAlignment=”Center”/></StackPanel></Border><StackPanel Grid.Row=”2" Margin=”0 0 0 60" ><TextBlock Text=”Overview” FontWeight=”Bold” FontSize=”24" /><Border Style=”{StaticResource BorderedPanel}”><TextBlock Text=”{Binding Overview}” TextWrapping=”Wrap” FontSize=”18"/></Border><TextBlock Text=”Genres” FontWeight=”Bold” FontSize=”24" /><Border Style=”{StaticResource BorderedPanel}”><ItemsControl ItemsSource=”{Binding Genres}”><ItemsControl.ItemsPanel><ItemsPanelTemplate><toolkit:WrapPanel Orientation=”Horizontal”/></ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate><DataTemplate><Border BorderBrush=”#32FFFFFF”BorderThickness=”1"CornerRadius=”2"Background=”#16000000"Margin=”5"><TextBlock Text=”{Binding Name}”FontSize=”14"Padding=”5"HorizontalAlignment=”Center”VerticalAlignment=”Center”/></Border></DataTemplate></ItemsControl.ItemTemplate></ItemsControl></Border><TextBlock Text=”Facts” FontWeight=”Bold” FontSize=”24" /><Border Style=”{StaticResource BorderedPanel}”><StackPanel><TextBlock Text=”Release Date” Style=”{StaticResource FactLabel}” /><TextBlock Text=”{Binding FormattedReleaseDate }”/><TextBlock Text=”Runtime” Style=”{StaticResource FactLabel}”/><TextBlock Text=”{Binding RuntimeFormatted}”/><TextBlock Text=”Budget” Style=”{StaticResource FactLabel}”/><TextBlock Text=”{Binding BudgetAsCurrencyString}”/><TextBlock Text=”Revenue” Style=”{StaticResource FactLabel}”/><TextBlock Text=”{Binding RevenueAsCurrencyString}”/><TextBlock Text=”Home Page” Style=”{StaticResource FactLabel}”/><HyperlinkButton NavigateUri=”{Binding HomePage}”><TextBlock Text=”{Binding HomePage}”TextTrimming=”CharacterEllipsis”MaxWidth=”300" /></HyperlinkButton></StackPanel></Border></StackPanel></Grid></ScrollViewer></Grid></Grid>

Step 12: Add a connected animation to the movie detail page.

Connected animations are a way to create a visually compelling transition between two different views, in this case, a transition from the MovieListPage to the MovieDetailPage using the element named “PosterImage” to maintain context between the two views.

  • Edit the MovieListPage.xaml.cs file and add the following code:
private static int persistedItemIndex;private async void MovieGridView_ItemClick(object sender, ItemClickEventArgs e){var movie = e.ClickedItem as Movie;if (movie == null){return;}persistedItemIndex = MovieGridView.Items.IndexOf(e.ClickedItem);var movieDetail = await _vm.GetMovieDetails(movie.Id);// Prepare connected animation to tie both poster images together.MovieGridView.PrepareConnectedAnimation(“poster”, movie, “PosterImage”);// Finally navigate to detail page and suppress default navigation transitions.Frame.Navigate(typeof(MovieDetailPage), movieDetail, new SuppressNavigationTransitionInfo());}

Before navigating to the MovieDetailPage, pre-fetch the movie details, including the image for the movie poster. This step is necessary for the animation to better tie the two elements together by ensuring the destination image has been loaded.

Astute readers may notice the persistedItemIndex static field used to store the index of the clicked item in the MovieGridView — this is a bit of a shortcut and will be used in Step 13 for the reverse connected animation, transitioning from the MovieDetailPage back to the MovieListPage.

Implementing connected animations is a two-step process: Prepare the animation in the source view, and start the animation in the destination view:

  • Edit the MovieDetailPage.xaml.cs file and add the following code to start the connected animation:
protected override void OnNavigatedTo(NavigationEventArgs e){base.OnNavigatedTo(e);var movie = e.Parameter as Movie;_vm.Movie = movie;// Start the connected animation prepared in the list view.var connectedAnimation = ConnectedAnimationService.GetForCurrentView().GetAnimation(“poster”);if (connectedAnimation != null){connectedAnimation.TryStart(this.PosterImage);}}

Step 13: Add a connected animation back to the movie list page.

While unidirectional connected animations are perfectly acceptable, creating bidirectional ones lets the Fluent Design System really shine.

  • Edit the MovieDetail.xaml.cs file and add the following code to prepare the animation. We’re relying on the app back button to provide navigation, so all we need to do is override the OnNavigatedFrom event handler.
protected override void OnNavigatedFrom(NavigationEventArgs e){base.OnNavigatedFrom(e);// Prepare the connected animation before returning to the list view.ConnectedAnimationService.GetForCurrentView().PrepareToAnimate(“fromDetailPoster”, this.PosterImage);}
  • Edit the MovieListPage.xaml.cs file and add the following code to the end of the OnNavitagatedTo event handler to start the animation:
// Only worry about the connection animation when navigating back to this page.if (e.NavigationMode == NavigationMode.Back){MovieGridView.Loaded += async (obj, args) =>{// Save and clear the default transitions to avoid conflicts with connected// animations.var transitions = MovieGridView.ItemContainerTransitions.ToList();MovieGridView.ItemContainerTransitions.Clear();var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation(“fromDetailPoster”);if (animation != null){var item = MovieGridView.Items[persistedItemIndex];MovieGridView.ScrollIntoView(item);// Small delay to give the view time to scroll into position before animating.await Task.Delay(100);await MovieGridView.TryStartConnectedAnimationAsync(animation, item, “PosterImage”);}transitions.ForEach(t => MovieGridView.ItemContainerTransitions.Add(t));};}

Step 1 4: Add the Parallax Effect to the background Image.

The parallax visual effect is another way to add motion and depth to an application. At this point, the MovieDetailPage has a boring white background. Spice it up by using the selected movie’s backdrop image (fortunately, TMDb API provides this image for us).

  • Edit the MovieDetaiPage.xaml file and add the following Xaml as the first child of the main Grid element.
<ParallaxView Source=”{x:Bind MovieDetails}” VerticalShift=”100"><Image x:Name=”BackgroundImage” Stretch=”UniformToFill”><Image.Source><BitmapImage UriSource=”{Binding BackdropPath}” /></Image.Source></Image></ParallaxView>

Here, we’re binding the source of the ParallaxView element to the element named “MovieDetails” (a ScrollViewer element we defined back in Step 11. Use the VerticalShift attribute to move the background up and down (you may have to fiddle with this value to get the effect you want) to enable vertical scroll in the view.

Step 15: Ad a custom composite effect to the background Image.

When binding elements to external images outside of your direct control, the images may not be suitable for using as backgrounds — they may be too dark, too light, or clash with the foreground. With new 2D effects available in the Win2D.uwp package, it’s easy to add effects to images to better suit design needs with negligible impact on performance.

At this point, if you were to run the sample application, the detail page would look something like this:

The background image is too dark for the selected movie, making the foreground text nearly impossible to read. With composite effects, this issue can be easily resolved.

  • Edit the MovieDetaiPage.xaml file and add change the ParallaxView element as follows:
<ParallaxView Source=”{x:Bind MovieDetails}” VerticalShift=”100"><Grid><Image x:Name=”BackgroundImage” Stretch=”UniformToFill”><Image.Source><BitmapImage UriSource=”{Binding BackdropPath}” /></Image.Source></Image><Canvas x:Name=”BackgroundHost” /></Grid></ParallaxView>
  • Edit the MovieDetailPage.xaml.cs file and add the following method:
private void InitializeBackgroundEffect(UIElement host){var hostVisual = ElementCompositionPreview.GetElementVisual(host);var compositor = hostVisual.Compositor;var effect = new GaussianBlurEffect{BlurAmount = 3.0f,BorderMode = EffectBorderMode.Hard,Source = new ArithmeticCompositeEffect{MultiplyAmount = 0,Source1Amount = 0.5f,Source2Amount = 0.5f,Source1 = new CompositionEffectSourceParameter(“backdropBrush”),Source2 = new ColorSourceEffect{Color = Color.FromArgb(255, 245, 245, 245)}}};var effectFactory = compositor.CreateEffectFactory(effect);var backdropBrush = compositor.CreateBackdropBrush();var effectBrush = effectFactory.CreateBrush();effectBrush.SetSourceParameter(“backdropBrush”, backdropBrush);var effectVisual = compositor.CreateSpriteVisual();effectVisual.Brush = effectBrush;ElementCompositionPreview.SetElementChildVisual(host, effectVisual);var bindSizeAnimation = compositor.CreateExpressionAnimation(“hostVisual.Size”);bindSizeAnimation.SetReferenceParameter(“hostVisual”, hostVisual);effectVisual.StartAnimation(“Size”, bindSizeAnimation);}
  • Edit the MovieDetailPage constructor to add the call to the InitializeBackgroundEffect() method:
public MovieDetailPage(){this.InitializeComponent();this.InitializeBackgroundEffect(this.BackgroundHost);
}

This effect will slightly blur and add a white tint to the backdrop image, allowing it to settle more naturally into the background.

Step 16: Taking the next steps.

With little effort, the Fluent Design system enables applications to be taken to new heights of visual excellence. This walkthrough only touches the surface of what can be done using UWP and the Fluent Design System. With a bit more work, you can add custom animations and content transitions, coordinated animations, and even more complex composite effects.

Please check out the full sample app, here.

And thanks to The Movie DB and its great free API.

--

--

Windows Developer
Windows Developer

Everything you need to know to develop great apps, games and other experiences for Windows.