SkiaSharp is a cross platform and low-level api. You draw in canvas with primitives like DrawText, DrawCircle, DrawPath. So it's very powerful but also requires some maths skills to make your own layouts.

All the following views have been made with SkiaSharp.

Drawing on top of Google Maps

This one was a bit challenging because you have to convert gps positions to pixel coordinates without calling the Google Maps SDK (to have good response time).
Fortunately I already solved this issue 10 years ago working on another project.

At this time we were rendering custom icons and paths with GDI+ on a Virtual Earth hosted in a web view. So I had already the mathematical Mercator projection magic :)

The remaining job was not difficult, since it's just drawing a path with shaders so we could show the horse effort with gradients.

This skiasharp bit was embedded in a custom ContentView called SessionMap.

The colors represent the effort of the horse, blue is light and red is maximum effort.

Drawing curves

Next to this map we wanted to show the horse effort (heart rate and speed), so we needed to draw curves over the horse training time.

We created a ContentView named SessionGraphView for this.

Linking the two

Of course we wanted some interaction. The user can drag the timeline along updating the effort number AND the matching position on the map.

This was achieved by binding property CurrentTime from the SessionGraphView to the SessionMap component.

Custom control

For another screen, we needed a date range selector indexed by month. Since such a control didn't exist in Xamarin Forms, we decided to implement it in SkiaSharp.

This is a simple control named MonthSlidesView embedded in a ContentView and exposes properties such as CurrentLowerDate and CurrentUpperDate.

Of course this control interacts with curves reflecting horse's progression over time.

Glowing number animation

This animation is 100% SkiaSharp, included in a SKCancasView named GlowingNumberView.

Zoom in on animation

CarouselView

One of the screen feature a carousel of all the horses which are currently training. We call it the Live screen.
So we needed a carousel view. Unfortunately the Xamarin.Forms CarouselView is still in pre alpha (for 2 years now :) https://www.nuget.org/packages/Xamarin.Forms.CarouselView.

I was disappointed with the performance and some resize issues, so we ended up forking it: https://github.com/roubachof/CarouselView. For example, on Android we switched from PageAdapter to FragmentStatePagerAdapter to avoid memory issues.

Horizontal/Grid-ListView

For this one, we wanted some specific behaviors:

With a horizontal layout, a snap effect should be applied to the first visible item

With a grid layout, we should be able to drag and drop items to reorder the collection

Since the items layout were complex, we wanted some view preloading to smoothen the scrolling

The Xamarin Forms ListView was too simple for this use.
So we dug the web and found this blog post: (https://causerexception.com/2018/02/06/xamarin-forms-ultimate-horizontal-list-guide/).
Unfortunately the implementation was very naive and the performance really bad (each time a view was retrieved, a new one was created, so no recycling...).
We simply had to reimplement from scratch a Forms ListView which we called HorizontalListView.

Implementation

On Android, we used a RecyclerView, snapping was achieved with the help of a LinearSnapHelper and drag and drop with a ItemTouchHelper.
For performance, we preload X item views asynchronously on a background thread.

On iOS, a UICollectionView was used. Drag and drop is fully supported and we use a simple trick to have the snap effect.

The implementation of this Xamarin Forms ListView will be uploaded to github soon.

BottomBar (ios style)

A custom navigation container was designed. At first it's really just a bottom tabbar, but if you swipe the tabbar up, a container taking all the screen reveals itself, showing a menu.
The menu contains the remaining available secondary actions, like user profile and settings.
This component is just a regular TabHostView and ViewSwitcher. But the TabHostView is positionned at the bottom of the screen.
When the component is at Peek state, only the bottom bar is shown.
Applying a slide gesture, we use a simple translation to move the whole view up and reveal the menu which was hidden so far.
Respectively, a slide down closes it.

Visual Studio App Center

We use app center for continuous integration. Each push on master triggers a build on Android and iOS.

We use a prebuild script to create 2 different applications based on the branch the build is running on. If we build an app on the qa branch, the app will be wired to our back office. But if it's built against the qa-mock, then all the data are mocked.

We also use the distribution feature to beta test our app with various users.

What we like the most about app center crash reports, is the ability to include some text with each report. Since we are logging relevant info in our app, we can attach our logs to each report to add specific context to the crash.

Xamarin Forms is mature AND powerful

Ok, so now we said it but we also shown it.

In the following weeks, I will publish posts on various aspects of the project. The HorizontalListView, TabHostView, TaskLoaderView, will be available on GitHub.