1 Comments
  •   Posted in: 
  • F#

A picture containing colour crayons

I recently was faced with the task to render RAL Colours on an app that I was developing. RAL Colours are used mainly in industrial colour appliances - i.e. powder coating. So while well known in the powder coating industry it was quite an exciting read on Wikipedia to find out how RAL colours came to life. The good thing is that there is a finite set of classic RAL colours. Even better there is a table on Wikipedia which contains a good enough approximation for the classic RAL colours.

So instead of copy & pasting the table into an editor and slashing away at the data. I was wondering if there would be a better way to extract the information from the website. And store the data in a more handy form such as a JSON file.

In the last couple of months, I have been dabbling with F# in my free time. Data providers are a powerful tool which is available in the F# language. In short, you can point a data provider at a data source, and during compilation, the types used in that source get generated for you. So for your typical JSON response from a website. You can use the JSON type provider to create a type based on that stream which you then can use throughout your F# program. Now, this is a more than your "create a C# POCO from JSON" Visual Studio feature. You also get methods to slice and dice through your data. In other words, it is an excellent tool for exploring new data sources or just parsing new data sources and processing that data.

As with LINQ extensions it is is possible to write your type providers. But for most general use cases the type provider already exists and can be added to your project as a NuGet package. The NuGet package we will be using is the FSharp.Data which provides type providers for JSON, XML, CSV and HTML (plus the World Bank ‍🤷‍♂️).

Using an F# script, we will first have to reference the type provider:

#I "./packages"
#r "FSharp.Data/lib/netstandard2.0/FSharp.Data.dll"

open FSharp.Data


Side note: I am using paket for my dependency management because it installs the package right into the project folder. You do not need to use paket, but you will have to make sure that the #r ... line points to the dll.

Now type providers create a type based on a data source. In our case I can point it at the Wikipedia website listing all the RAL colours:

type wikipedia = HtmlProvider<"https://en.wikipedia.org/wiki/List_of_RAL_colors">

We could have also provided a local file:

type wikipedia = HtmlProvider<"list_of_ral_colors.html">

The local file is excellent if you do not always want to hit the remote site. But you run the risk of having an older version locally than on the server which can lead to ugly problems. As far as we are concerned for the script. I will point it at Wikipedia and be sure to make my again annual donation at the end of year

In the JSON file, we will want to store the RAL, RGB and colour name. So let's create a record type for that quickly:

type ralColor = { ral: string; hex: string; name: string}

Now that we have our types, we are all set to extract that data. By looking at the website, we can see in which section the table is located:

Picture showing part of the Wikipedia RalColor List

Knowing this location, we can scan the site and hone in on the data we are looking for:

let ralColorSection = wikipedia.Load("https://en.wikipedia.org/wiki/List_of_RAL_colors")
                                .Tables
                                .``All RAL Colours in a single listing``

If you have never used type providers, you will be probably reading the lines above and go: "Okay... I guess..." - so let's just quickly look at what happened underneath those lines of code. As the name suggests, type providers provide a type based on a data source. This is where we nod. So what do we get with the lines above? We get a type which represents the table of RAL colours. We can access all of the rows via ralColorSection.Rows. When iterating over each row we can read the value in a column by using its name. So we could print out all colour names as follows:

ralColorSection.Rows |> Seq.iter (fun r -> printfn "%s" r.``Colour name``)

I know this is freaking cool right! So if we wanted to extract the RAL, RGB and name from the table we could use our previously defined type and the values as follows:

let ralColors = ralColorSection.Rows
                    |> Seq.map((fun r -> 
                        {ral = r.``RAL Number``; 
                            hex = r.``HEX Triplet``; 
                            name = r.``Colour name``}))

Note the two ticks are how F# variables with spaces in them can be accessed. Now we have all the data we wanted. So now all that is left to do is the boring bit of storing it into a JSON file:

#I "./packages"
#r "Newtonsoft.Json/lib/netstandard2.0/Newtonsoft.Json.dll"

// ...

open Newtonsoft.Json

// ...

let writeToJsonFile ralColors =
    let filePath = Path.Combine(__SOURCE_DIRECTORY__, "ral_colour_map.json")
    let jsonString = JsonConvert.SerializeObject(ralColors)
    File.WriteAllText(filePath, jsonString, Encoding.UTF8) |> ignore

And that wraps up this blog post. I hope you have seen that F# 's type providers can be a great way to scan through data sources and extract the information you need. One thing to be aware of when using type providers: You can't directly share the generated type with other .Net languages such as C#. You would have to wrap the data in a record type - by the way: the type we created to hold the subset of data is a record type. So while there might be some additional effort up ahead when writing fully-fledged enterprise applications, they are a no brainer for scripting. And will provide you with a significant productivity boost when exploring new datasets.

Be sure to check out the official documentation on the HTML provider used in this post. As always you can find the entire code on GitHub.

HTH

0 Comments

Ever since I have received my Azure IoT Devkit, I wanted to create a small app with it. The app would let me play around with streaming data from the device and view it on my phone. Also sending data to the device and many other exciting aspects of creating an IoT application. So what better way than to create a system that would stream the sensor data from my devkit to my mobile phone. Once that is implemented, how about creating an alerting system. Should a value increase over a certain threshold, the system will notify me. Many exciting ideas and paired with the capabilities of Azure all in my grasp. So before implementing, let me show you my high-level system design:

System Overview showing the IoT Kit, the different Azure services and the Xamarin mobile app.

However, first we will need to create an app on the device or emulate a device that sends up a stream of data to the Azure cloud over the IoT Hub. Then we will probably want to stream the data to the mobile client using SignalR. And finally visualise all of the data using some nice Xamarin Forms code - perhaps even a fancy charting library.

Once the data is getting streamed to the client let's have a look at alarming scenarios. What if the value e.g. the humidity rises quickly over a short timeframe. We should be able to detect such an event using Stream Analytics and then send a push notification to a client.

SignalR vs IoT Hub

Before diving into the implementation I showed this overview to a friend of mine - to make sure I am not overdoing it with the Azure-candy store. And promptly I got the question: "Hey Mark, so what you are basically doing is a Publish and Subscribe system - why do you need SignalR and IoT Hub. Wouldn't IoT Hub or SignalR offer all you need to send messages at scale to clients?". What a great question - and simplification of the problem. While it is right that what we are doing is nothing else then publishing data and subscribing to it. They are two worlds we are combining here. On the one side we have the IoT world. Here we the creator/company/enterprise produce the software and often also distribute the hardware. So we own the device and software. On the other hand when we release an app we often do not own the device on which the app is running on. So while we generally tend to trust our IoT devices because we create them, harden them and equip them with certificates for communication with our backend - in our case Azure IoT Hub. We generally do not have the same trust in mobile apps. Mobile apps are often deployed to the mobile store and therefore have no guarantee that the app does not end up on a rooted Android or Jailbreaked iOS phone. Once on such a device is often just a cat and mouse game to make it as difficult as possible for an attacker to access the secrets that got installed with the app. In short IoT apps and mobile apps come from a different starting position and therefore we tend to use different approaches for implementing security. And that is why we use two pub/sub systems, because both of them were designed with the two different aspects in mind.

In the next blog post we will get started with writing the IoT client and also see how we can write an IoT client without requiring a devkit.

0 Comments

A view of Big Ben at night with traffic lights going by.

Reactive Extensions (Rx.Net) was released in 2009 and therefore is celebrating it's 10th anniversary this year. Reactive Extensions is well known as a solution approach for event-based systems. However, it also features many other helpful features, such as timers! I guess the title of the blog might have given this one away - nonetheless let me show you why Rx.Net provides you with a great alternative to the standard .Net timer(s).

Usually, timers serve for two scenarios. Delaying the execution of a certain piece of logic until a specified later time or to periodically execute some logic. For example, in network stacks, it is common to send a heartbeat / keep-alive message every n-seconds to let the counterpart know that the communication partner is still alive, and the connection should be kept open. We could implement such a general timer as such:

public class LiveBit : IDisposable
{
    private readonly INetworkInterface _networkInterface;
    private readonly Timer _timer;

    public LiveBit(INetworkInterface networkInterface)
    {
        _networkInterface = networkInterface;
        _timer = new Timer(1000);
        _timer.Elapsed += SendLiveBit;
        _timer.AutoReset = true;
        _timer.Enabled = true;
    }

    public void Dispose()
    {
        _timer.Dispose();
    }

    private void SendLiveBit(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Send Live Bit");
        var liveBit = new byte[]{0xAA}; // Some imaginative payload
        _networkInterface.Send(liveBit);
    }
}

The code is implemented using only the .Net library and does not use Rx.Net. So why should we even bother to replace this piece of code? Well, how would one go and test this code? We could write a Test looking something like this:

[Fact]
public async Task LiveBit_WhenCreated_TheSendMethodWillBeInvokedAfter1Second()
{
    // Arrange: Given a mock interface ...
    int counter = 0;
    // Using Moq https://www.nuget.org/packages/Moq/
    var networkInterfaceMock = new Mock<INetworkInterface>();
    // Write a function that counts the number of invocations
    networkInterfaceMock
        .Setup(n => n.Send(It.IsAny<IEnumerable<Byte>>()))
        .Callback(() => counter++);
    // Act: ... start the livebit service and wait for a good second ...
    var liveBit = new LiveBit(networkInterfaceMock.Object);
    await Task.Delay(TimeSpan.FromMilliseconds(1100));
    // Assert: ... the mocked send method has been invoked once.
    Assert.Equal(1, counter);
}

To be honest whenever I see an await Task.Delay(someNumber) it never feels right. Usually, this is always some hack. I am not saying you should never do this, but in 95% of all cases, they are an indication of bad programming. However, what else can we do? "Shift time by one second!" - Sure, but how would you do that? Well, let me show you. First, let's rewrite the timer function to use the Rx.Net approach:

public class ReactiveLiveBit : IDisposable
{
    private readonly INetworkInterface _networkInterface;
    private readonly IDisposable _timer;

    public ReactiveLiveBit(INetworkInterface networkInterface)
    {
        _networkInterface = networkInterface;
        _timer = Observable
            .Interval(TimeSpan.FromSeconds(1))
            .Subscribe(x => SendLiveBit());
    }

    public void Dispose()
    {
        _timer.Dispose();
    }

    private void SendLiveBit()
    {
        Console.WriteLine("Send Live Bit");
        var liveBit = new byte[]{0xAA}; // Some imaginative payload
        _networkInterface.Send(liveBit);
    }
}

We can rerun our test, and it is still passing. However, the delay is still present in our test code. Looking at the definition of Rx.Net Scheduler, we see that it takes an IScheduler as an argument. This means that we can inject the time (ticker) into our scheduler - in other words, we can play timelords. So if we rewrite our constructor a bit:

public ReactiveLiveBit(INetworkInterface networkInterface, IScheduler scheduler = null)
{
    var timerScheduler = scheduler ?? Scheduler.Default;
    _networkInterface = networkInterface;
    _timer = Observable
        .Interval(TimeSpan.FromSeconds(1), timerScheduler)
        .Subscribe(x => SendLiveBit());
}

We now pass in an optional parameter of IScheduler which is set to null by default. Moreover, if the parameter is not set, we use the Scheduler.Default. So if we do not inject a scheduler, the method uses the system clock and a second is a second. To test this, we can rerun our test at this point to find it still snoozing in the green.

When testing with Rx.Net, there is a dedicated NuGet package Microsoft.Reactive.Testing that provides some excellent helpers such as the TestScheduler.

Using the TestScheduler we can rewrite our test code like this:

[Fact]
public void ReactiveLiveBit_WhenCreatedWithATestScheduler_TheSendMethodWillBeInvoked1TestSecond()
{
    // Arrange: Given a mock interface ...
    int counter = 0;
    // Using Moq https://www.nuget.org/packages/Moq/
    var networkInterfaceMock = new Mock<INetworkInterface>();
    // Write a function that counts the number of invocations
    networkInterfaceMock
        .Setup(n => n.Send(It.IsAny<IEnumerable<Byte>>()))
        .Callback(() => counter++);
    var testScheduler = new TestScheduler();
    // Act: ... start the livebit service and wait for a good second ...
    var liveBit = new ReactiveLiveBit(networkInterfaceMock.Object, testScheduler);
    testScheduler.AdvanceBy(TimeSpan.FromSeconds(1).Ticks);
    // Assert: ... the mocked send method has been invoked once.
    Assert.Equal(1, counter);
}

Utilising the TestScheduler allows us to move forward in time with the AdvanceBy method. Forwarding the time will execute the timer code and reduce our test execution time to mere milliseconds.

Conclusion

So do you need Rx.Net to write timers? No, you do not - then again do you need C# to write applications instead of using assembler? Again no, you don't, but it helps to ship stable and maintainable code. Be sure to check out the official Rx.Net website to find more resources on Rx.Net.

You can find all the code to this small sample on GitHub.

HTH

0 Comments

Showing a wodden peer and the ocean on a sunny day

Fabulousallows writing Xamarin Forms apps with F#in a functional style. Fabulous has been inspired byElm, which proved that by using the Model View Update (MVU for short) pattern functional languages are great for writing UI code. While functional code squashes a plethora of potential bugs around null and race conditions - in this post, we will not focus on that aspect of Fabulous. Instead, let us look at how you can create beautiful UIs that stay maintainable in the future.

This blog post is part of the Xamarin UI July organised bySteven Thewissen. Be sure to check out all the beautiful posts by myfellow co-authors.

Featured #XamarinUIJuly Badge

Inspired by some of Stevens previous posts on - what I like to call - lickable UI. I wanted to show why writing UI in code allows you to write UI that is not only beautiful but easy to maintain and extend. So for this post, I will be implementing a design idea I found onDribbblebyApptaste.

App design as shown on dribbble

Though this blog post will focus on Fabulous, you could apply the same principle when writing your app using C#and XAML. But you will end up with a bunch of files, and it will feel more complicated. F#a terse language to write to begin with and Fabulous allow for writing apps with fewer lines of code than what you usually require with C#and XAML. I am not saying this is what should be your reason to check out Fabulous. But it is a fact that... If you are new to F#and Fabulous next comes a short intro. If this is all old news to you feel free to skip the intro.

A short intro to Fabulous

Let's start with the good oldWelcome to Xamarin Formsblank app:

module App = 
    type Model = 
      { Message : string } // your apps state, we could do without...

    type Msg = 
        | SomeStateChange // just for the demo, we do not need this...

    let initModel = { Message = "Welcome to Xamarin.Forms!" }

    let init () = initModel, Cmd.none

    let update msg model =
        match msg with
        | SomeStateChange -> model, Cmd.none

    let view (model: Model) dispatch =
        View.ContentPage(
          content = View.StackLayout(
            children = [ 
                View.Label(text = model.Message, horizontalOptions = LayoutOptions.Center, verticalOptions = LayoutOptions.CenterAndExpand)
            ]))

    // Note, this declaration is needed if you enable LiveUpdate
    let program = Program.mkProgram init update view

type App () as app = 
    inherit Application ()

    let runner = 
        App.program
#if DEBUG
        |> Program.withConsoleTrace
#endif
        |> XamarinFormsProgram.run app

Yes, this is all the code you would usually have in your blank C#app. We will not go into too much detail on how all the functions work. At the bottom, you can see thetype App, which translates to theApp.xaml.csclass, i.e. the entry point of any Xamarin Forms app. Our analogue to theMainPageis themodule App. The three components of the MVU pattern are present with theModel(an F#record, if your new to F#think of it as a POCO, not quite the same but close enough for now) and theviewandupdatefunctions.

The update function is where all changes of the view are processed. Displaying only text this function has nothing to do really. Since we will be focusing on the UI later, I will give you a short intro to what the update function does in your average app. Imagine all your UI changes and background task events must gosequentiallythrough this point. All state changes are defined. You can reproduce every state of the app - oh and no race conditions

The view function contains theContentPage, which includes aStackLayoutand aLabel. At first, you might not think much about it. But look how terse it is written. For example, theStackLayoutchildren, that is a simple list in F#. So adding another element to the grid would be simply adding a new UI element.

The functions get invoked by Fabulous and do not interact with Xamarin Forms directly. This is important to understand because this means that all of the code you write can be 100% unit tested. All the dependencies to the view are resolved within the Fabulous framework. Theviewfunction returns the instructions on how to create the UI, but it does not create it. If you change a value such as the welcome message, the Fabulous Framework checks what parts have changed and updates the view accordingly. The React.JS framework uses the same technique with a shadow DOM (Document Object Model) that is then taken to update the actual UI.

Atomic Design and coded UIs

Writing your UI with code comes with a few perks. While you could write all of your UI in theviewfunction. It might get a bit hard to view at a glance over time. But being only code, you can split up the code into different functions. This also allows you to reuse parts of the UI in different places. And reusability reusing/combining components is at the heart of Atomic Design.

Atomic Design

While unique design, reusable components sound all great, let's have a look at how we could design such an app with Fabulous. We want to start with the essential elements (Atoms) which we then put together to more significant UI components and in the end the Page.

When we look at the design of the app, we can see that most of the title labels seem to have the same font. Another UI component that quickly gets my eye is the cards holding the description of the destination and the things to do:

DestinationDescription

Now what we can see is that titles have the same font, are bold and apart from the cards in the"Things to do"section have the same font size. So let's create a function that allows us to create a title label with the parameters text and font size:

let titleLabel text fontSize =
    View.Label(text = text,
        fontSize = fontSize,
        textColor = textColor,
        verticalOptions = LayoutOptions.Center,
        fontAttributes = FontAttributes.Bold)

The destination is shown by a picture (gorgeous pictures if I may say so! ) and a short description of the town, country, rating and a favourite It seems that the favourite should be clickable so let's assume that is a button. Probably similar to the search button on the top right. Keeping accessibility in mind, I prefer to use buttons or platform interactive controls in general if an interaction is required by the user. This way, it will be easier to optimize the experience using a screen reader. So we want a button with an icon - or a text. Since Xamarin Forms allows us to use custom fonts, we could use a font such asFont Awesometo provide us with scalable icons. Be sure to check outJames'poston how to use Font Awesome with your Xamarin Forms app. So let's create a function that given the icon, colour, background colour and command function returns us with the button:

let materialFont =
    (match Device.RuntimePlatform with
                             | Device.iOS -> "Material Design Icons"
                             | Device.Android -> "materialdesignicons-webfont.ttf#Material Design Icons"
                             | _ -> null)

let materialButton materialIcon backgroundColor textColor command =
    View.Button(text = materialIcon,
        command = command,
        fontFamily = materialFont,
        fontSize = 20.,
        backgroundColor = backgroundColor,
        widthRequest = 42.,
        textColor = textColor)

So now to the description text i.e. the country. Lets again create a function that will create a label given the text:

let descriptionLabel text =
    View.Label(text = text,
        textColor = secondaryTextColor,
        fontSize = descriptionFontSize
        )

Did you notice the title and description pattern is repeated in the"Things to do"section of the page. Up to now we have created what Atomic Design calls Atoms. Now let's pack some of those atoms into a coherent block such (Molecule):

let titleAndDescription title titleFontSize description =
    View.StackLayout(margin = 0.,
        children=[
            titleLabel title titleFontSize
            descriptionLabel description |> fun(label) -> label.Margin (Thickness(0.,-8.,0.,0.))]

This will allow us to reuse the Title & Description duo further. Also, note that we had to adjust the margin a bit. You can think of the|>as a pipe forward. Since we have a View type, we can pipe it forward to a lambda function where we change the margin. Calling the margin function will again return a View type. If you are using LINQ, you most probably have joined multiple calls to where select et al. - we are doing the exact same thing here.

Now looking back at the short description of the destination, we can also see a rating of the city with stars. So let's create a function that given the icon and text colour returns aLabelbased on font awesome.

let materialIcon materialIcon color =
    View.Label(text = materialIcon,
        textColor = color,
        fontFamily = materialFont,
        fontSize = 18.,
        verticalOptions = LayoutOptions.Center,
        fontAttributes = FontAttributes.Bold)

The rating bar - I assume it is a read-only indicator that shows me an overall rating between zero to five. Given a rating of 4.5, we want four full stars and one covered by half. So let's take this control apart, let's say we want one function that only draws the star for a certain percentage:

let ratingStar percentage =
    let star = materialIcon star starColor
    let boxViewWidth = 16. - (16. * percentage)
    View.Grid(
        padding = 0.,
        margin = Thickness(0.,-4.,0.,0.),
        children = [
            star
            View.BoxView(color = backgroundColor, 
                widthRequest = boxViewWidth,
                isVisible = (if percentage > 0. then true else false),
                horizontalOptions = LayoutOptions.End)
            ])

The function aka star factory is called by another function that draws N stars given the rating:

let ratingControl (rating:decimal) =
    let fullNumber = Math.Ceiling(rating)
    let fraction = (rating - Math.Truncate(rating))
    View.StackLayout(orientation = StackOrientation.Horizontal,
        children = [
            for i in 1m .. fullNumber -> if i = fullNumber then ratingStar (float fraction) else ratingStar 1.
        ])

Now we have all of our building blocks together for the description, but we still have the image with rounded corners left. A quick look at theImageViewfrom Xamarin Forms tells us:"No rounded edges."But when putting the image in aFrame, we can create the rounded edges effect. So let's create a function that gives us an image with round corners:

let roundedCornerImage imagePath =
    View.Frame(cornerRadius = cornerRadius,
        padding = 0.,
        isClippedToBounds = true,
        hasShadow = true,
        content = View.Image(
            source = imagePath,
            aspect = Aspect.AspectFill)
    )

The parts are all made now let's assemble them so that we get the Image with rounded corners overlaid by a short description:

let cityDescriptionFrame city dispatch =
    View.StackLayout(
        margin = Thickness(16.,0.,16.,0.),
        children = [
            (roundedCornerImage city.Image |> fun(img) -> img.HeightRequest 320.)
            View.Frame(
                heightRequest = 70.,
                margin = Thickness(24.,-64.,24.,0.),
                padding = Thickness(20.,12.,16.,12.),
                backgroundColor = Color.White,
                cornerRadius = cornerRadius,
                content = View.Grid(
                    rowdefs=["auto"; "auto" ],
                    coldefs=["*";"auto"],
                    children=[
                        (titleAndDescription city.Name titleFontSize city.Country)
                        (favoriteIcon city dispatch).GridColumn(2)
                        (ratingControl city.Rating).GridRow(1).GridColumnSpan(2)
                        ]
                ),
                hasShadow = true)
        ])

Similarly, we can implement the"Things to do"section. The great thing is we can reuse a lot of components that we have already created. Then we can put all the parts together in the view method which presents us with the following UI:

AppScreenshot

You can find the entire sample onGitHub.

Side notes: No, we are not required to have all the code in one file. But since this is a one-pager application, I left it together, so it is easier to navigate the code in a browser. Further note that theCarouselViewdid not work correctly when I was working with the view. I hope I will be soon able to get it working and have a sample which will allow switching between cities as intended by design.

Conclusion

Applying the Atomic Design pattern to your UI can really make your app easier to maintain and create. Given that Fabulous allows writing your UI in code, it is relatively straight forward to create a custom and consistent UI without much boilerplate code. Further Fabulous offers a live update feature which allows you to live code during a debug session. Not only does the UI adapt, but also the logic is executed. You can read more aboutthe live update featureon the official site.

It seems that writing UI with code is coming back into style during the recent days of 2019. With companies like Apple working on Swift UI. If you are a die-hard C#lover, you should check out thePost by Ryan Davison writing UIs with C#for Xamarin.

You can read more about the Atomic Design pattern onBrad Frosts website.

4 Comments

Image of an escalator going towards the light

This post is part of the Xamarin Month, which is about community and love. Looking after a nice UI and User Experience is one way how a product team or developer can show love to its user. So let focus on a small detail which always makes me smile when done right 🙂

Xamarin Forms apps have a reputation for taking their time to load. While quicker loading times are always preferred and are an excellent place to start. Sometimes there is no way around letting the user wait, while a background process is doing it's best to do its task. However, there is an alternative to speed: Distraction. Distraction is what Airplanes do with their onboard entertainment, and it is what some apps like Twitter do on startup with an animated logo. Since Xamarin Apps fall into the latter category, let's see how we can improve our startup experience with some fancy animated Xamarin Hexagon.

However, before we get started with the animation part, I'm afraid we have to take a quick look into one of our platform projects - into the Android project that is.

The empty feeling when starting Xamarin.Forms on Android

Have you ever wondered why the startup screen experience of your Xamarin app on Android differs from iOS or UWP? While we are greeted instantly with a logo when starting up our Xamarin.iOS app, when starting the same app on Android, a blank screen stares at us. Why is that so?

Screenshot_1550416214

Just point it out: this is not the fault of Xamarin Forms, it is more a difference in the two platforms. While iOS forces you to provide a startup storyboard (a single view), there is no such thing under Android. At least that may seem so at first. However, from where is this blank screen? You probably already know that the starting point of a Xamarin.Forms app on Android is the MainActivity.cs or to be more precise that one activity which has the following attribute set:

[Activity( ... Theme = "@style/MainTheme", MainLauncher = true, ... ]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
	// ...
}

One attribute that is getting set is the theme. This theme is where Android "draws it's inspiration" for the splash screen. We can find it defined under Resources\values\styles.xml. Now to replicate the startup image, we first have to define a layout in Resources\drawables\splash_screen.xml along the following lines:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <color android:color="@color/colorPrimary"/>
  </item>
  <item>
    <bitmap
        android:src="@drawable/SplashScreen"
        android:tileMode="disabled"
        android:gravity="center" />
  </item>
</layer-list>

Now we can modify styles.xml by adding new style with the following lines:

<?xml version="1.0" encoding="utf-8" ?>
<resources>

  <!-- ... -->

  <style name="SplashTheme" parent ="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@drawable/splash_screen</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowFullscreen">true</item>
  </style>
</resources>

Starting the app and we see the Xamarin logo while starting up. Unfortunately, it does not go away when we get to our Hello World page in Xamarin Forms. The reason being that we have overwritten the default style which is also used by our Xamarin.Forms app. However, we can fix this by adding an activity solely to display this new style, once the new SplashActivity.cs is rendered we switch over to the current MainActivity.cs. The MainActivity.cs uses the original style and starts the Xamarin.Forms part of our app.

Screenshot_1550416896

If we let the app run the app now. We do see a splash screen which disappears after starting up the app. So now that we have Android on par with iOS and UWP let's shift gears and implement that bouncy startup animation.

Bouncy startup animation

Drawing some inspiration from the Twitter app, let's let our logo bounce similarly. We implement the animation of the hexagon in Xamarin.Forms. The animation could - in a real app - buy us some time while we are starting up. So what we need is again a splash screen but this time a Xamarin.Forms view. The XAML displays an image in the centre:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomSplash.SplashPage"
             BackgroundColor="#2196F3">
    <ContentPage.Content>
        <Grid>
            <Image x:Name="SplashIcon"
                   HorizontalOptions="Center"
                   VerticalOptions="Center"
                   Source="SplashScreen.png" />
        </Grid>
    </ContentPage.Content>
</ContentPage>

The XAML is ready. However, this would solely extend the static native splash screens. The animation takes place in the code behind. We can override the OnAppearing method and add some animation logic to it:

await SplashIcon.ScaleTo(0.5, 500, Easing.CubicInOut);
var animationTasks = new[]{
    SplashIcon.ScaleTo(100.0, 1000, Easing.CubicInOut),
    SplashIcon.FadeTo(0, 700, Easing.CubicInOut)
};
await Task.WhenAll(animationTasks);

First, we shrink the image, then we expand and simultaneously let it go transparent. Combining the animations gives our app a nice fluid effect. While we could now put this puppy in a loop and endeavour it forever and ever and ever and... well most probably we only want to show it once and then move on to our main page. The following lines achieve this:

Navigation.InsertPageBefore(new MainPage(), Navigation.NavigationStack[0]);
await Navigation.PopToRootAsync(false);

The above lines insert the main page as the first page in the navigation stack. In other words, we insert the main page before the splash screen. Then we PopToRoot so the splash screen is no longer present on the navigation. So while the lines might look a bit odd at first. They prevent the user from navigating back to the splash page. Further, it allows the splash page to be garbage collected. Bottom line all the things we want to do with a splash screen once it has served its purpose.

The resulting app looks something like this:

Animation splash screen on iOS

I am a firm believer that these little things can go a long way and show your user right from the get-go that you care about your app. While the native splash screen is a good start. The animated load screen can buy you a bit of extra time to start up your app while distracting the user. You can find the entire demo app on GitHub.

Be sure to check out the other blog posts in the Xamarin Universe and happy coding!