Category Archives: UX

Using a TreeView Control for Navigation in UWP

In this article we’ll show how to use a TreeView as the main navigation control in a UWP app. We will stay as close as possible to the Fluent Design principles and other current UI guidelines.

Our first approach was to rely on the NavigationView control, since it comes with a full user experience (navigation, hamburger, page title, secondary commands, responsive and fluent design). Unfortunately it is entirely focused on (read: limited to) a flat list of menu items. So we decided to design and build the entire user experience from scratch.

We admit that we expected to run into issues. None of the native UWP apps that could clearly use treeview based navigation –such as the Mail client and the OneNote app- actually have one. So we were a bit suspicious of the TreeView’s capabilities. Fortunately this was just unfounded fear.

We created a sample app with these main navigation components in a Shell page:

  • a SplitView,
  • a TreeView for primary navigation,
  • a Frame to host the pages on a background with parallax effect,
  • a Hamburger button, and
  • a CommandBar for secondary navigation.

Here’s how that app looks like:
TreeViewNavigation

Building the User Experience

Here’s the main XAML content of the Shell page:

<!-- SplitView -->
<SplitView x:Name="ShellSplitView">
    <SplitView.Pane>
        <Grid x:Name="SplitViewPane">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
            </Grid.RowDefinitions>
            <!-- Navigation Tree -->
            <TreeView x:Name="NavigationTree"
                        ItemInvoked="TreeView_ItemInvoked"
                        Style="{StaticResource TreeViewStyle1}" />
            <!-- Command Bar -->
            <CommandBar>
                <!-- AppBarButtons -->
            </CommandBar>
        </Grid>
    </SplitView.Pane>
    <SplitView.Content>
        <Grid>
            <!-- Does not seem to work. -->
            <ParallaxView Source="{Binding ElementName=NavigationTree}"
                            VerticalShift="100">
                <!-- Background Image -->
            </ParallaxView>

            <!-- Navigation Frame -->
            <Frame x:Name="SplitViewFrame"
                    Navigated="SplitViewFrame_OnNavigated"/>
        </Grid>
    </SplitView.Content>
</SplitView>

<!-- Title Bar -->
<TextBlock x:Name="AppTitle" />

<!-- Hamburger Button -->
<Button x:Name="HamburgerButton">
    <!-- ... -->
</Button>

SplitView

We used a classic SplitView control to host the main components: the TreeView on the left and a Frame to hold the current page on the right. The SplitView Pane can be opened or closed with a Hamburger button that sits on top of it (z-index wise).

A SplitView supports four display modes for the Pane, but the NavigationView only uses three display modes for the menu:

  • Minimal: panel shows if needed and on top of content,
  • Compact: panel shows a narrow band of icons, and
  • Expanded: panel shows alongside the content.

We didn’t use icons in the TreeView’s ItemTemplate – and it would anyway be impossible to  to show a multi-level tree in a narrow vertical band. So we decided to skip compact mode in the visual states. As a result the SplitView Pane has always the same width (when visible). It will just toggle between Inline and Expanded according to the app’s width.

Following the guidelines for Acrylic, we made the navigation pane background

  • 60% in-app acrylic in overlay mode, and
  • 60% background acrylic in side-by-side mode.

When using acrylic brushes in your app, don’t forget to provide a fallback color. It’s the solid color that is shown when the composition brushes are not used – i.e. when the app loses focus, or when the user settings or the machine hardware prevent it. Here’s a screenshot of the app when it does not have the focus:

Unfocused

Here’s the definition of the corresponding brushes:

<!-- Splitview Pane -->
<AcrylicBrush x:Key="SplitViewInlineBackgroundBrush"
                BackgroundSource="HostBackdrop"
                TintOpacity="0.6"
                FallbackColor="#ffe6ff" />
<AcrylicBrush x:Key="SplitViewOverlayBackgroundBrush"
                BackgroundSource="Backdrop"
                TintOpacity="0.6"
                FallbackColor="#ffe6ff" />

And here’s how they are declaratively applied in the Visual State Manager:

<!-- VisualState to be triggered when window width is >=1007 effective pixels -->
<VisualState x:Name="Expanded">
    <VisualState.StateTriggers>
        <AdaptiveTrigger MinWindowWidth="1007" />
    </VisualState.StateTriggers>
    <VisualState.Setters>
        <!-- SplitView pane shows as overlay -->
        <Setter Target="ShellSplitView.DisplayMode"
                Value="Inline" />
        <Setter Target="ShellSplitView.PaneBackground"
                Value="{StaticResource SplitViewInlineBackgroundBrush}" />
    </VisualState.Setters>
</VisualState>

The Shell page -including the SplitView and its content- is blended into the title area:

// Blends the app into the title bar.
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
titleBar.ButtonForegroundColor = (Color)Application.Current.Resources["TitlebarButtonForegroundColor"];

For more info on this code and its consequences, check the TitleBar Customization documentation.

TreeView

The TreeView control is the obvious candidate for displaying a hierarchical menu. It is also one of the UWP controls that comes with built-in Reveal highlight effect, a lighting effect that highlights interactive elements, such as command bar buttons, listview items, or treeview nodes when the user moves the pointer near them. Check the bottom left part of the first screenshot in this article for an impression.

We tweaked the TreeViewItem style a little bit to decorate the selected node with a thin vertical bar, just like the NavigationView does (but without an animation). Here’s what we changed :

<!-- Added -->
<Grid x:Name="SelectionGrid"
        Width="4"
        Margin="8"
        HorizontalAlignment="Left" />

<VisualState x:Name="Selected">
    <VisualState.Setters>
        <!-- Changed -->
        <Setter Target="SelectionGrid.Background"
                Value="{ThemeResource TreeViewItemBackgroundSelected}" />
        <Setter Target="ContentPresenter.Foreground"
                Value="{ThemeResource TreeViewItemForegroundSelected}" />
        <Setter Target="ContentPresenterGrid.BorderBrush"
                Value="{ThemeResource TreeViewItemBorderBrushSelected}" />
    </VisualState.Setters>
</VisualState>

As part of the process, we also changed the different accent colors so that we don’t rely on the user’s personal accent color:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <!-- AccentColor overrides -->
            <!-- Shades of OrangeRed -->
            <ResourceDictionary x:Key="Default">
                <Color x:Key="SystemAccentColor">#ff4500</Color>
                <Color x:Key="SystemAccentColorLight1">#ff4500</Color>
                <Color x:Key="SystemAccentColorLight2">#ff8f66</Color>
                <Color x:Key="SystemAccentColorLight3">#b33000</Color>
                <Color x:Key="SystemAccentColorDark1">#ff4500</Color>
                <Color x:Key="SystemAccentColorDark2">#ff8f66</Color>
                <Color x:Key="SystemAccentColorDark3">#b33000</Color>
            </ResourceDictionary>
            <!-- ... -->

Here’s how all of this looks like – before and after the template and color changes:
WithoutVisualChanges

WithVisualChanges

Notice that we also moved the whole TreeView control some pixels to the left, to vertically align the chevron icons with the Hamburger button.

Hamburger button

We decided to give the Hamburger button the same size and padding as the system buttons (minimize, maximize, and close) and place it into the title bar in the top left corner. If you place input controls in the title bar, then you should override the default interactive part of the title bar (the part that responds to dragging and double clicking) – otherwise your control will not be reachable.

Here’s the XAML for the top left corner:

<!-- Hamburger Button -->
<Button x:Name="HamburgerButton"
        Margin="0"
        Width="48"
        Height="32"
        <!-- ... -->

<!-- Title Bar -->
<Grid x:Name="AppTitleBar"
        Background="Transparent"
        Height="32"
        VerticalAlignment="Top"
        HorizontalAlignment="Stretch">
    <TextBlock x:Name="AppTitle"
                xmlns:appmodel="using:Windows.ApplicationModel"
                Text="{x:Bind appmodel:Package.Current.DisplayName}"
                Style="{StaticResource CaptionTextBlockStyle}"
                IsHitTestVisible="False"
                Margin="48 8 0 0" />
</Grid>

Here’s how the default title bar zone is overridden:

Window.Current.SetTitleBar(AppTitleBar);

The code behind the Hamburger button is straightforward. It just needs to toggle IsPaneOpen on the SplitView:

/// <summary>
/// Toggles the SplitView pane.
/// </summary>
private void HamburgerButton_Click(object sender, RoutedEventArgs e)
{
    ShellSplitView.IsPaneOpen = !ShellSplitView.IsPaneOpen;
}

Secondary commands

For the secondary commands at the bottom of the navigation panel, we opted for a CommandBar with regular app bar buttons. It’s one of the controls that comes with the Reveal effect built in, and it has the correct size. We considered buttons of the same dimensions as the Hamburger and the system buttons, but this size is to small for buttons that are used often and that have more complex icons.

Navigation

Our focus of the sample app was mainly on the user experience, so we kept the functional part -the navigation itself- as simple as possible. All the related code is placed directly in the Shell page, albeit in a partial class file. In a real-world app you would build a Navigation Service and then find and call it using singletons, dependency injection, service locator, or any other kind of blood magic. For more info, please check my older blog post on SplitView navigation.

To separate at least some of the concerns, we did create a NavigationMenuItem class that allows to define a hierarchic navigation structure (with the destination page type and parameter, and a Children collection):
NavigationMenuItem

Here’s a part of the logical navigation menu in the sample app:

private ObservableCollection<NavigationMenuItem> MainMenu => 
    new ObservableCollection<NavigationMenuItem>
        {
            new NavigationMenuItem
            {
                Text = "Edged Weapons",
                NavigationDestination = typeof(BladesPage),
                Children = new ObservableCollection<MenuItem>
                {
                    new NavigationMenuItem
                    {
                        Text = "Arakh",
                        NavigationDestination = typeof(BladesPage),
                        NavigationParameter = "Arakh"
                    },
                    new NavigationMenuItem
                    {
                        Text = "Dragonglass",
                        NavigationDestination = typeof(BladesPage),
                        NavigationParameter = "Dragonglass"
                    },
                    // ...

The Navigate method uses this information to … well … navigate:

/// <summary>
/// Navigates to the specified source page type.
/// </summary>
public bool Navigate(Type sourcePageType, object parameter = null)
{
    return SplitViewFrame.Navigate(sourcePageType, parameter);
}

When the app starts up, TreeView nodes are created from the menu structure – with a little help from a recursive extension method:

internal static TreeViewNode AsTreeViewNode(this NavigationMenuItem menuItem)
{
    var result = new TreeViewNode
    {
        Content = menuItem
    };

    foreach (NavigationMenuItem subItem in menuItem.Children)
    {
        result.Children.Add(subItem.AsTreeViewNode());
    }

    return result;
}
/// <summary>
/// Populates the TreeView from the Menu.
/// </summary>
private void PopulateTreeView()
{
    // Populate the tree.
    foreach (var item in MainMenu)
    {
        NavigationTree.RootNodes.Add(item.AsTreeViewNode());
    }
}

Each node in the TreeView now has a NavigationMenuItem as its Content, so it knows which page to load and with which parameter. Here’s what happens when a node is clicked:

/// <summary>
/// Navigates to the corresponding treeview selection.
/// </summary>
private void TreeView_ItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args)
{
    if (args.InvokedItem is TreeViewNode node)
    {
        if (node.Content is NavigationMenuItem menuItem)
        {
            var target = menuItem.NavigationDestination;
            if (target != null)
            {
                Navigate(menuItem.NavigationDestination, menuItem.NavigationParameter);
            }
        }
    }
}

The secondary command buttons call the same method, but without a parameter:

private void SettingsButton_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
    Navigate(typeof(SettingsPage));
}

Just to prove that the parameter from the NavigationMenuItem is correctly passed to the Page, here’s how the different pages in the sample app update their subtitle in the top right corner:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (e.Parameter != null)
    {
        SubTitle.Text = e.Parameter.ToString();
    }

    base.OnNavigatedTo(e);
}

The Back Button

The hierarchical menu on the left -together with the secondary commands at the bottom- give the user immediate access to any page in the app. So personally we’re not in favor of providing a back button. But just for the sake of completeness, we also implemented it.

This implies a method to navigate back:

/// <summary>
/// Returns to the previous page.
/// </summary>
public void GoBack()
{
    if (SplitViewFrame.CanGoBack)
    {
        SplitViewFrame.GoBack();
    }
}

And you also need to make the system button visible:

/// <summary>
/// Shows the system back button.
/// </summary>
public void EnableBackButton()
{
    var navManager = SystemNavigationManager.GetForCurrentView();
    navManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    navManager.BackRequested -= (s, e) => GoBack();
    navManager.BackRequested += (s, e) => GoBack();
}

We placed the Hamburger button in the top left corner. When the system back button (dis)appears, we need to shift that button together with the text block holding the app title:

// Update the title bar when the back button (dis)appears or resizes.
Window.Current.CoreWindow.SizeChanged += (s, e) => UpdateAppTitle();
coreTitleBar.LayoutMetricsChanged += (s, e) => UpdateAppTitle();
/// <summary>
/// Updates the title bar when the back button (dis)appears or resizes.
/// </summary>
private void UpdateAppTitle()
{
    var full = (ApplicationView.GetForCurrentView().IsFullScreenMode);
    var left = (full ? 0 : CoreApplication.GetCurrentView().TitleBar.SystemOverlayLeftInset);
    HamburgerButton.Margin = new Thickness(left, 0, 0, 0);
    AppTitle.Margin = new Thickness(left + HamburgerButton.Width + 12, 8, 0, 0);
}

We also added the code to unselect the current TreeView node when the Back or a secondary command button is pressed. Since we weren’t successful in programmatically selecting and unselecting nodes, we applied the old trick of toggling the SelectionMode:

/// <summary>
/// Makes the TreeView lose its selection when there is no corresponding main menu item.
/// </summary>
/// <remarks>This works, but I don't know why...</remarks>
private void SplitViewFrame_OnNavigated(object sender, NavigationEventArgs e)
{
    NavigationTree.SelectionMode = TreeViewSelectionMode.None;
    NavigationTree.SelectionMode = TreeViewSelectionMode.Single;
}

We assumed it would be necessary to add some extra code to determine whether the navigation was triggered by the TreeView or not, before deciding to unselect the current node. It turns out that unconditionally toggling the selection mode seems to do the job already. But honestly: this feels like a coincidence.

NavigationTreeView, first of his name ?

We just created a great looking fluent design compatible TreeView based navigation UI. The development was easier than we expected, and the results look better than we expected. Some of you may be tempted to componentize all of this into a user experience just like the current NavigationView control. We think that this can be done with not too much extra effort, but personally we prefer the more granular control that we have in the sample app.

That sample app lives here on GitHub.

Enjoy!

Advertisements

An Extended Splash Screen with Lottie Animations in UWP

In this article we demonstrate how to use Lottie animations in the extended splash screen of a UWP application. A Lottie animation is a programmable animated graphic that can be rendered into your XAML.

Here’s how the companion sample app starts up, with its splash screen transitioning into an look-alike page that displays an animation, whilst executing some longer-running code:

AppStart

Creating an extended splash screen

Sometimes an app needs to execute some longer-running code on startup. Especially the very first time after an install or an upgrade, you may want to connect to the backend, create a user profile, populate a local SQLite database, and defeat the Klingons, the Sith and/or the Daleks.

The long-running code in my sample app is less ambitious:

await Task.Delay(10000);

It is common to handle this scenario with a so-called Extended Splash Screen. This is a page that looks like the native splash screen and that executes the longer-running code, before eventually navigating to the main page. Typically an extended splash screen is decorated with a progress ring to indicate that the app does not hang.

The nice official documentation for creating an extended the splash screen is right here. I started with a copy of the sample code from there, and replaced the progress ring by a Lottie animation.

In a nutshell, here’s the routine to create an extended splash screen:

  • get the position of the SplashScreen image from the LaunchActivatedEventArgs,
  • navigate to an extended splash screen page that displays the same image at the same location,
  • execute the long running code in the Dismissed event handler of the original splash screen, and finally
  • navigate to the ‘real’ homepage or shell.

Adding Lottie capabilities

Lottie is a library to render animations. It uses JSON files that were generated by the Bodymovin extension of Adobe After Effects, a Special Effects editor to create picture and SVG animations. Lottie has implementations for iOS, Android, and the Web (React Native). It is supported by a broad community and has won a number of awards as design and development tool. It seems fair to assume that Lottie is becoming one of the standards for stand-alone animations in apps.

For Native Windows developers, Lottie is now available as LottieUWP, a NuGet package written by Alexandre Chohfi. To look it up from Visual Studio, you need to check the ‘Include prerelease’ box in NuGet Package Manager:

LottieUWP_NuGet

Adding Lottie files

LottieFiles is a great resource to get some free JSON files to experiment with:

LottieFiles

That’s where I found the beer bubbles animation.

Add the downloaded JSON file(s) to your project, and don’t forget to change their Build Action to Content:

Json_Build_Action

Displaying Lottie animations

The best way to get some insight into LottieUWP and its API is viewing this #ifdef episode on Channel 9. For the sample app, I just added a LottieAnimationView in the extended splash screen, with an auto-played, infinite-looping animation, nicely positioned over the beer glass background:


That’s all that’s needed to host and run the animation. I just modified the Speed – programmatically, since assigning a value declaratively in XAML is not very well supported in the current LottieUWP version (after all it *is* a pre-release):

// Adjust the speed of the Lottie animation.
SplashScreenAnimation.Speed = 3;

The end-user may resize the window or rotate his device when the app is starting. So when the background image is repositioned we also have to update the size and location of the LottieAnimationView:

// Position the extended splash screen image in the same location as the system splash screen image.
private void PositionImage()
{
    extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
    extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
    extendedSplashImage.Height = splashImageRect.Height;
    extendedSplashImage.Width = splashImageRect.Width;

    // Position the Lottie animation.
    var factor = splashImageRect.Width / 620;
    SplashScreenAnimation.SetValue(Canvas.LeftProperty, splashImageRect.X + 100 * factor);
    SplashScreenAnimation.SetValue(Canvas.TopProperty, splashImageRect.Y + 150 * factor);
    SplashScreenAnimation.Width = 180 * factor;
}

Tweaking the JSON files

Visual Studio allows you to unminify the JSON file, this will reveal a structure of layers with the strokes and shapes and their use in animations and transformations. I assume that it’s unlikely that we’re going to apply changes manually in there. Nevertheless there are some ways to slightly tweak the files.

In LottieFile’s preview page you can visualize the selected JSON against different background colors. This helps you to reveal the color scheme that is used in the animation. Here you can see that the filter animation uses plain white to fill the circles – so they’re not transparent:

LottiePreview

The button in the top right corner launches the Lottie Editor:

LottieEditor

This page allows you to change the color of some elements. The corresponding changes to the JSON files are logged in the browser’s Console.

Other use cases

The main page of the sample app shows how to decorate a button with a (more or less) subtle animation to draw the user’s attention. This is how it looks like:

AppMain

Please note that the animated GIF on this page loops infinitely, unlike the animation in the UWP app.

Again, we used a LottieAnimationView, but we set the RepeatCount to 2 and the RepeatMode to Reverse to obtain a brief symmetric animation:


And again, we adjusted the speed programmatically:

// Adjust the speed of the animation.
// Does not work declaratively for now.
MainpageAnimation.Speed = 3F;

Use PlayAnimation to (re)play the Lottie animation:

// Replay the animation.
MainpageAnimation.PlayAnimation();

I just added this call to verify whether the button is still clickable when the animation is running on top of it. Fortunately this is the case.

if you want see more Lottie API examples, please check Corrado’s blog post on the subject.

GitHub Repo N° 50

The sample app lives here on GitHub in my 50th public repo.

Enjoy!

A Fluent Button Flyout for UWP

In this article we describe how to build an elegantly designed and animated fluent ToggleButton-Popup combination for use in UWP apps as an alternative for the less fluent Button Flyout. The code is not mine, I merely reused code and components from the Continuity framework by Justin Liu. This frameworks contains a lot of helpers for implementing Fluent Design in your apps without needing Windows 10 Fall Creators Update.

The ToggleButton-Popup combo is an excellent widget to display extra information such as a help text.

Here’s how all of this may look like (styling is up to you of course). It starts with a stand-alone round ‘more’ button, with hover animations. When pressed, the button rotates toward the opening flyout, while changing its shape to look like a ‘close’ button that becomes connected to the content that was just revealed. In the mean time, the flyout itself opens with a scale animation as if it grew out of the button:

FluentFlyoutButton

Closing the button and dismissing the flyout come with reverse animations.

I’ve been looking for ways to animate opening and closing Flyout or ContentDialog instances. I went through many of the XAML animations techniques, but could not find a way. Flyout and ContentDialog don’t come with Visual States, so Visual Transitions are not an option. Although its name seems promising, PopInThemeAnimation is not applicable. And if it were, it doesn’t come with a scale animation (only opacity and translation).

I almost gave up, and tried to to accept that flyouts would always open and close like this:

DefaultFlyoutButton

Frankly, I don’t like the animations. But what’s worse: you can not even see which of the buttons was actually pressed…

Then I came across this sample Kliva design with exactly the user experience I was looking for:

ContinuityPanel

I decided to copy the relevant code into my own solution under Features/Continuity to get some Fluent-As-A-Service:

ContinuityClasses

The Kliva demo is not using a Button with its Flyout, but a ToggleButton with ‘just’ a Grid. My only mission was to replace the Grid with a Popup. After a few iterations, I came up with the following setup, which even allows the Popup to have IsLightDismissEnabled on.:

  • A toggle button with storyboarded animations is placed in a container
  • A Popup is placed next to it with
  • The content of the Popup (not the Popup itself) is given implicit Show and Hide Composition API animations.

Here’s the corresponding XAML definition:

<!-- Toggle Button -->
<continuity:CircularToggleButton x:Name="TheToggle"
                                    CheckedBackground="{StaticResource HighlightBrush}"
                                    CheckedCornerRadius="6 0 0 6"
                                    FontFamily="Segoe UI">
    <continuity:CircularToggleButton.CheckedContent>
        <ContentControl Margin="3"
                        Style="{StaticResource IconCloseStyle}" />
    </continuity:CircularToggleButton.CheckedContent>
    <ContentControl Style="{StaticResource IconMoreStyle}" />
</continuity:CircularToggleButton>
<!-- 'Flyout' -->
<Popup x:Name="ThePopup"
        IsOpen="{Binding IsChecked, ElementName=TheToggle, Mode=TwoWay}"
        IsLightDismissEnabled="False"
        HorizontalOffset="{Binding ActualWidth, ElementName=TheToggle}"
        VerticalOffset="-20">
    <Grid x:Name="TheGrid"
            Visibility="{Binding IsOpen, ElementName=ThePopup}">
        <!-- Content -->
    </Grid>
</Popup>

That’s it! Let’s dive into some details.

An animated circular toggle button

The CircularToggleButton adds a few dependency properties to ToggleButton, like content, background color and corner radius for the different states:

public sealed class CircularToggleButton : ToggleButton
{
    public static readonly DependencyProperty CheckedContentProperty =
        DependencyProperty.Register(
            "CheckedContent",
            typeof(object),
            typeof(CircularToggleButton),
            new PropertyMetadata(null));

    public object CheckedContent
    {
        get => GetValue(CheckedContentProperty);
        set => SetValue(CheckedContentProperty, value);
    }

    // ..
}

It also comes with a circular custom style and some nice visual effects and animations.

Here’s how the PointerOver VisualState pumps up the size of the content using a RenderTransform with a CompositeTransform on ScaleX and ScaleY:

<VisualState x:Name="PointerOver">
    <VisualState.Setters>
        <Setter Target="CheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
                Value="1.1" />
        <Setter Target="CheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
                Value="1.1" />
        <Setter Target="UncheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
                Value="1.1" />
        <Setter Target="UncheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
                Value="1.1" />
        <Setter Target="BackgroundVisual.Opacity"
                Value="0.9" />
    </VisualState.Setters>
</VisualState>

Here’s the VisualTransition with the StoryBoard on CornerRadius that turns the round button into its ‘connected’ shape when checked:

<VisualTransition GeneratedDuration="0:0:0.25"
                    To="Checked">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.CornerRadius)"
                                        Storyboard.TargetName="BackgroundVisual">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="{Binding CheckedCornerRadius, RelativeSource={RelativeSource TemplatedParent}}" />
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualTransition>

If you want to know more about storyboarded animations, this circular toggle button style definition is a nice tutorial. Storyboarded animations are a way to change a dependency property over time. When there’s a visual impact of this, the animation may or may not require the UI thread. While the SDK’s evolve, more and more of these animations are internally rewritten to run on the composition thread. So there’s no need for you give up readable declarative Storyboards in XAML in favor of dark imperative code against the Composition API. But for the second part of this article, we’ll use the latter…

An animated Popup

The Popup control is a XAML container that allows you to place content on top of other content. You can not animate the Popup itself but fortunately you can animate its content. As promised we’ll use Composition animations for this. These are 60-frames-per-second animations that run independent of the UI thread. They’re a bit harder to write, but there are a lot of helpers available, like these from UWP Community Toolkit.

Here’s the Continuity helper that starts it all:

TheGrid.EnableFluidVisibilityAnimation(
    centerPoint: new Vector3(0.0f, 40.0f, 0.0f), 
    showFromScale: 0.2f, 
    hideToScale: 0.2f, 
    showDuration: 400, 
    hideDuration: 400);

Here’s part of its implementation.

A time based Composition API animation of the type Vector2KeyFrameAnimation is created with the Scale of the Visual as Target:

if (!showFromScale.Equals(1.0f))
{
    showeScaleAnimation = compositor.CreateVector2KeyFrameAnimation();
    showeScaleAnimation.InsertKeyFrame(0.0f, new Vector2(showFromScale));
    showeScaleAnimation.InsertKeyFrame(1.0f, Vector2.One);
    showeScaleAnimation.Duration = TimeSpan.FromMilliseconds(showDuration);
    showeScaleAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay);
    showeScaleAnimation.Target = "Scale.XY";
}

The different animations (scale, position, opacity, …) are placed together in an AnimationGroup (one for hide and one for show):

var showAnimationGroup = compositor.CreateAnimationGroup();
// ...
if (showeScaleAnimation != null)
{
    showAnimationGroup.Add(showeScaleAnimation);
}

These animation groups are then implicitly hooked to the Popup’s content, using SetImplicitShowAnimation and SetImplicitHideAnimation:

ElementCompositionPreview.SetImplicitShowAnimation(element, showAnimationGroup);

Under the hood, a lot of different animation techniques were used to create this user experience, but I love the result! And while it’s probably possible to forge this into a single custom control, I’m not sure if it would add much value….

The code

The ‘fluent button flyout’ sample lives here on Github, the inspiring Continuity by Justin Liu is right here.

Enjoy!

How to generate an Adobe Color Swatch and transform it to XAML brushes

There are a lot of good free web sites that can create a group of matching colors for you. While it’s nice to go online and create such a palette, it’s another thing to transform a –sometimes lengthy- list of colors on an HTML page into something that can be used in XAML, e.g. a list of brush definitions.

Luckily, most of these web sites have one thing in common: they allow you to export the color palette to a so-called Color Swatch. That’s an Adobe Photoshop file format for storing a list of named colors. Photoshop uses the .aco extension for this file type.

In this blog post, I’ll introduce you to some of these web sites, and I also present a Portable Class Library project together with a Universal Windows Platform app to read a Color Swatch, and export its content to a list of XAML SolidColorBrush definitions that you can use as a resource.

How to create a color palette

Here are some approaches that you can take to come up with a consistent color palette for your app.

The mathematical approach

In the mathematical approach, you hand pick one or two primary colors and calculate the rest of the palette. This calculation is based on the position of the colors in a color wheel. The generated theme will contain your selected base colors, plus their adjacent (a.k.a. analog or harmonious) colors or triad colors or tetrad colors, and optionally their complementary color.

There are a lot of web sites with an interactive color wheel, such as Adobe itself and ColorsOnTheWeb, but I always keep coming back to Paletton:

paletton

Not only does this site allow you to interactively design a color palette, it also has a lot of preview options: site samples, drawings, and even animations. It also allows you to export the color scheme to different formats, including XML, CSS, and ACO:

paletton_export

There is a lot more in color theory and color psychology than just the color wheel: warmth, shades, tints, hue, and so on. But unless you are a talented designer, a color palette based on the color wheel will have better harmony and contrast (and hence will be better perceived by your users) than a random set of hand picked colors.

The image approach

A second approach for generating a color scheme is analyzing the pixels of an image that you find attractive. There a a lot of web sites around that create a color palette out of an image that you upload.

Here’s an example of a palette that was generated from the picture of a fox, by Pictaculous:

Pictaculous

The site not only returns the colors of the calculated palette, but also links to related color schemes that are stored in the libraries of Adobe Kuler and ColourLovers. There’s also an API for all of this. The export format for Pictaculous is … Adobe Photoshop Color Swatch.

Every site or tool uses a different algorithm to pick scheme colors, so you may want to shop around. Here’s what Adobe –my favorite site for this approach- generates from that same fox:

AdobeColorCC

With the image-to-palette approach you rely on the inherent beauty and harmony of nature. Well … more probably you rely on the talent of a photographer, artist, fashion designer, or film maker. When they create an image, they do that with a color palette in mind. That palette is based on … the color wheel. Here’s a nice introduction to cinematic color design, and there are more examples at MoviesInColor (which unfortunately has no export feature).

By the way, it’s not only photos from nature that yield nice color palettes. Here’s what CSSDrive generates from a photo of a city:

cssdrive

Themes that are generated by CSS Drive can be saved as CSS or ACO.

Hint: if you’re looking for candidate pictures for this approach, any Bing background will do:

bing

Get a designer

Of course you can also get a professional graphic designer to create a color palette for you. The odds are very high that he or she will come up with an Adobe Color Swatch. That’s also what Google’s Material Design’s designers have done: you can download all of their color palettes right here. It should be no surprise that this is … an .aco file.

Reading an Adobe Color Swatch file

I was getting tired of copy-pasting individual hexadecimal color codes out of HTML, and into XAML. So I was pleased to discover that they all support the .aco format. The next step was building a Universal Windows Platform app to transform the list of named colors in a Color Swatch into a list of XAML SolidColorBrush definitions.

The C# code that reads the color swatch content is written by Richard Moss, and described in this excellent article. I just copy-pasted the algorithm out of its Windows Forms application into a stand-alone Portable Class Library. So it can be called now from any .NET environment, including Xamarin. I removed the references to File and Color from the original code (they don’t exist in PCL), and stored the algorithm in its own class.

The AcoConverter class has only one public method –ReadPhotoShopSwatchFile– that takes a stream –the content of the .aco file- and returns a collection of SwatchColor – a small helper class.

AcoConverterVS

I also created an UWP app that lets you select a Color Swatch through a FileOpenPicker, visualize the palette, and export it to a list of XAML SolidColorBrush definitions through a FileSavePicker.

Here’s a palette from Paletton:

paletton2

This is how that palette looks like in the app:

AcoConverter

And here’s the export:

<SolidColorBrush x:Key='Primary color 1' Color='#FFAA3939' /> 
<SolidColorBrush x:Key='Primary color 2' Color='#FFFF5555' /> 
<SolidColorBrush x:Key='Primary color 3' Color='#FFF35151' /> 
<SolidColorBrush x:Key='Primary color 4' Color='#FF612020' /> 
<SolidColorBrush x:Key='Primary color 5' Color='#FF180808' /> 
<SolidColorBrush x:Key='Secondary color (1) 1' Color='#FF226666' /> 
<SolidColorBrush x:Key='Secondary color (1) 2' Color='#FF4BE2E2' /> 
<SolidColorBrush x:Key='Secondary color (1) 3' Color='#FF319292' /> 
<SolidColorBrush x:Key='Secondary color (1) 4' Color='#FF133A3A' /> 
<SolidColorBrush x:Key='Secondary color (1) 5' Color='#FF050E0E' /> 
<SolidColorBrush x:Key='Secondary color (2) 1' Color='#FF7B9F35' /> 
<SolidColorBrush x:Key='Secondary color (2) 2' Color='#FFC3FA53' /> 
<SolidColorBrush x:Key='Secondary color (2) 3' Color='#FFB0E34C' /> 
<SolidColorBrush x:Key='Secondary color (2) 4' Color='#FF465A1E' /> 
<SolidColorBrush x:Key='Secondary color (2) 5' Color='#FF111607' />

Source code

The source code lives here on GitHub. As already mentioned, the core logic is in a PCL project, so it can be called from any .NET environment.

Enjoy!