Adding smooth transitions when navigating in your UWP app

Early this week, I published a new version of UrzaGatherer which added support to navigation transitions.

You can see how it looks in this video:

 

I like these transitions because they really smooth out the user experience. You feel more comfortable using the app just thanks to these subtle animations.

So let me explain you how you can do the same.

General idea

The overall idea is pretty simple. We will use a split view and its ability to embed a frame (which is the host of the navigation).

Just before navigating, we will render the client area of the split view to a picture.

This picture will be added on top of the frame while the frame is navigating.

Then based on the effect you want to achieve, you can play with the picture.

In my example, I slowly animate the picture opacity from 1 to 0 to make it disappear.

To make it just a little bit more dynamic I also translate the frame itself to give user the impression that the frame is coming from the bottom.

Pretty simple, right? Let’s now see how to implement it.

Implementation

First of all, let’s start with a simple split view:

Capture

This split view contains a picture control and a content control that you need to bind to a frame:

frame = new Frame { Language = ApplicationLanguages.Languages[0] };

SplitContent.Content = frame;

Once connected, you can ask the frame to navigate to a specific page:

frame.Navigate(typeof(Page1));

So the idea is to save the frame content to a picture when navigating. To do so we first need a method to capture frame’s content and save it to the picture control:

RenderTargetBitmap rtb = new RenderTargetBitmap();
async Task StartDissolvingAsync()
{
    try
    {
        await rtb.RenderAsync(SplitContent);
        DissolveImage.Source = rtb;

        DissolveImage.Visibility = Visibility.Visible;
        DissolveImage.Opacity = 1.0;
        AnimateDouble(DissolveImage, "Opacity", 0.0, 200, () =>
        {
            DissolveImage.Visibility = Visibility.Collapsed;
        });

        SplitContentTransform.Y = 25;
        AnimateDouble(SplitContentTransform, "Y", 0, 150);
    }
    catch
    {
        // Ignore error
        DissolveImage.Visibility = Visibility.Collapsed;
    }
}

We are using a RenderTargetBitmap to save the current frame texture. This image is then displayed by the picture control on top of the frame.

Animations are done using storyboards thanks to this method:

public static void AnimateDouble(DependencyObject target, string path, double to, double duration, Action onCompleted = null)
{
    var animation = new DoubleAnimation
    {
        EnableDependentAnimation = true,
        To = to,
        Duration = new Duration(TimeSpan.FromMilliseconds(duration))
    };
    Storyboard.SetTarget(animation, target);
    Storyboard.SetTargetProperty(animation, path);

    var sb = new Storyboard();
    sb.Children.Add(animation);

    if (onCompleted != null)
    {
        sb.Completed += (s, e) =>
        {
            onCompleted();
        };
    }

    sb.Begin();
}

Last step is to actually launch the dissolve effect before navigating:

private async void Page1_Click(object sender, RoutedEventArgs e)
{
    await StartDissolvingAsync();
    frame.Navigate(typeof(Page1));
}

private async void Page2_Click(object sender, RoutedEventArgs e)
{
    await StartDissolvingAsync();
    frame.Navigate(typeof(Page2));
}

That’s it! Now you are ready to create better looking applications! (Please find the Visual studio project here…).