lundi 19 février 2018

Building a Placeholder Loading UI like Facebook using only XAML for your UWP application [XAML,C#,Composition]

Building beautiful native UI is very important, and keeping your users informed of what is going in the app is even more important.

We are going to look at creating a placeholder loading control that looks like what facebook is using in its application.

Here is a static version of the loading control:


Here is what we could do if we add some animation using composition.

It is super important to remember that the loading animation should not hide or distract the user from using y our application, the loading animation should just be there to help your user understand that they must wait a bit for the loading to end.

For this example we will be build 2 different UI loaders to show that data is being loaded, here is what the placeholders will have to show that they are loading:



Here is an example of what we want to do:


You have two options either we have a control with a shimmer over to simulate that something is loading or we just have a static rectangle (or grid) with a background color.   If you only want to use the backgroudn color you can look at the RectangleNoShimmerControl.xaml file, if you do want the shimmer keep on reading =).

First we are going to create a RectangleControl UserControl that will hold a ContentControl and a StackPanel with a FontIcon.

The ContentControl with its LinearGradientBrush is what will allow you have the gradient effect when we move the element, in the samlpe you can change: 
<GradientStop Offset="0.5" Color="#dcdcdc" />
by
<GradientStop Offset="0.5" Color="Red" />

which will give you this for example:

Next we will need to add the animation on the content control, we need something to move on the X axis, so using a DoubleAnimationUsingKeyFrames  and targeting  CompositeTransform.TranslateX  we will be able to do this.

<Storyboard>
    <DoubleAnimationUsingKeyFrames
            EnableDependentAnimation="True"
            RepeatBehavior="Forever"
Storyboard.TargetName="contentControl" Storyboard.TargetProperty="(Control.Foreground).(Brush.RelativeTransform).(CompositeTransform.TranslateX)"> <EasingDoubleKeyFrame KeyTime="0" Value="-1" /> <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1" /> </DoubleAnimationUsingKeyFrames> </Storyboard>

We are going to nest our Storyboard inside a <Grid.Triggers> =>        <EventTrigger RoutedEvent="Grid.Loaded"> => <EventTrigger.Actions> which will allow us to start the animation when the Grid is loaded.

Here is the full XAML code for the page:

    <UserControl.Resources>         
        <Color x:Key="EmptyStateLightgray">#ebebeb</Color>
        <Color x:Key="EmptyStatebackground">#f7f7f7</Color>
        <SolidColorBrush x:Key="EmptyStateColorBrush" Color="{StaticResource EmptyStateLightgray}" />
    </UserControl.Resources>

     <Grid>
        <Grid.Triggers>
            <EventTrigger RoutedEvent="Grid.Loaded">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames
                                EnableDependentAnimation="True"
                                RepeatBehavior="Forever"
                                Storyboard.TargetName="contentControl"
                                Storyboard.TargetProperty="(Control.Foreground).(Brush.RelativeTransform).(CompositeTransform.TranslateX)">
                                <EasingDoubleKeyFrame KeyTime="0" Value="-1" />
                                <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
        </Grid.Triggers>
<ContentControl x:Name="contentControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch"> <ContentControl.Foreground> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <LinearGradientBrush.RelativeTransform> <CompositeTransform CenterX="0.5" CenterY="0.5" Rotation="95" /> </LinearGradientBrush.RelativeTransform> <GradientStop Offset="0" Color="{StaticResource EmptyStateLightgray}" /> <GradientStop Offset="0.5" Color="#dcdcdc" /> <GradientStop Offset="1" Color="{StaticResource EmptyStateLightgray}" /> </LinearGradientBrush> </ContentControl.Foreground> <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{StaticResource EmptyStateColorBrush}"> <FontIcon FontSize="800" Glyph="&#xE009;" /> </StackPanel> </ContentControl> </Grid>


Now that we have our Facebook like shimmer animation we will create our loading states using that UserControl. Now we are going to create another UserControl to resemble something like this:
To create this in XAML I will use a Grid which will use multiple RowDefinitions , which gives us this:


<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="120" />
            <RowDefinition Height="15" />
            <RowDefinition Height="20" />
            <RowDefinition Height="15" />
        </Grid.RowDefinitions>

        <local:RectangleControl
            Grid.Row="0"
            Width="290"
            Margin="0"
            />
        <local:RectangleControl
            Grid.Row="1"
            Width="60"
            Margin="0,5,0,0"
            />
        <local:RectangleControl
            Grid.Row="2"
            Width="210"
            Margin="0,9,0,0"
            />
        <local:RectangleControl
            Grid.Row="3"
            Width="170"
            Margin="0,5,0,0"
            />
    </Grid>

You can find my code sample here.
Happy coding