Bad Form (in Xamarin)

3 July 2017

Here at Instil, we make no bones about the fact that we've been enjoying Xamarin for cross-platform mobile development for a number of years now. With a handful of shipped applications and lots more development scheduled, we continue to see the benefits to using this framework and have enjoyed success with it. Alongside a reduced development time from shared codebases, developing in C# 6.0 – and more recently 7.0 – feels like a truly mature and modern approach, and fits with our workflow nicely.

My colleague Matthew touched on this topic back in late 2015 in his blog post entitled Xamarin: A Panacea for Cross-Platform Mobile Development? but here we'll see that Xamarin is not always what you think it might be. Like most tools, there is always a danger that you could be using it incorrectly.

Xamarin Forms

Now, when we say 'Xamarin' and 'cross-platform' lots of people may immediately think of the single codebase, write-once-deploy-everywhere style of development offered specifically by Xamarin's more simplistic offspring: Xamarin Forms. Leveraging the Xamarin native mobile frameworks internally, Forms aims to provide a way to code interfaces and business logic together in a single project and deploy to multiple platforms as a native application installed on each. Sounds great right? Well, not exactly.

In order to do this, Forms needed to make a lot of decisions for you about how your app will look and feel. Common platform-specific interface components are abstracted to a single Forms-based component, which is then translated accordingly depending on the platform for which the Forms project is currently being built. With so much constant innovation happening in mobile user interfaces, this isn't likely to feel very 'native' to your mobile developers or even the users of your app. The result is an often over-simplified interface that looks and feels rather immature.

Childishly Simple

If a mobile app built with Forms doesn't look as polished or perform as smoothly, that is by design. In response to some complaints from developers directed at Xamarin Forms in April 2015, CEO Nat Friedman was quick to try and clarify the distinction between Xamarin Forms and native development using Xamarin:

I do want to be clear that Xamarin.Forms is not Xamarin. It's a library that we built to help people quickly write very simple, data-entry style apps. That's why it's called "Forms." It's not intended to be highly performant or to replicate all the per-platform APIs in Xamarin.iOS and Xamarin.Android. For that, you should use the native APIs

Furthermore, he expressed how simpified Forms was intended to be:

Before release, we had internally called Xamarin.Forms "duplo," to emphasize that it was for childishly-simple apps and screens…

This gives some key insight into not only how Xamarin intend their Forms library to be used but also their own internal decision to compromise on performance and customisability in order to deliver it. By abstracting lots of the core platform-specific APIs into a single write-once API developers can quickly write 'childishly-simple apps' at the expense of later customising or tweaking them. Some teams may be innovating in spite of Forms but no new user experiences are being innovated because of it.

The Good

Originally inspired in many ways by WPF, Forms allows developers to create user interfaces in XAML, cleanly separating UI creation from models and business logic. This encourages an MVVM approach and helps steer developers away from cluttering models with UI code, promoting a more easily testable model design. The XAML then interacts with C# through the use of bindings. This is by all arguments a powerful pattern and the simplcity of the syntax makes adding bindings a breeze:

<Label x:Name="UsernameLabel" Text="{Binding User.Name}" TextColor="White">

Alongside this, Forms provides a standard way to transform values set on these bindings via a ValueConverter. Again this can be accessed through a simple, reusable interface in the XAML meaning that values can be transformed and consumed with ease. A simple example might be taking a User object as a property of the binding context and converting it to a username for text on a label.

<ResourceDictionary>
	<valueConverters:UserToNameConverter x:Key="UsernameConverter"/>
</ResourceDictionary>
...
<Label x:Name="UsernameLabel" Text="{Binding User, Converter={StaticResource UsernameConverter}}" TextColor="White">

Finally, to play devils advocate, Forms' simplicity could also be seen as one of its strengths. Perhaps you're aiming for a quick proof of concept of a cross-platform app; maybe you don't have a complex design and just want a vanilla interface so you can focus on the functionality. In either case, the rapidity of developing basic screens with Forms could aid a quick win.

The Bad

That said however, any perceived advantages arguably go nowhere near far enough to outweigh the limitations of using Forms to create bespoke, performant applications. To be clear, if your goal is to create an application with these qualities in mind, Forms should be avoided at all costs.

Firstly, iOS and Android developers will be lost within Forms initially. Arguably, once Forms apps are installed, they are 'native' applications, but this is not native app development. Those embarking on a Forms project will not be learning native development but rather 'Forms development' and there are few transferable skills. Teams may be considering Forms due to their in-house .Net and C# experience, or perhaps since they have small iOS and Android teams respectively and need to maximise output by sharing code. Unless the aim is a basic PoC project, in both instances Xamarin native would still be a better fit. Sure, some training on the native SDKs for each platform might be required, but the increase in product quality is worth the time invested, and the knowledge is easily transferred to standard mobile app development without Xamarin.

Xamarin Forms continues to get regular updates and, on modern mobile devices, any perceived performance lag is reasonably negligible but certain devices, particularly lower-end Android devices often still suffer. Developers will always be at the mercy of the Forms translational layer. As recently as just a few weeks ago, the Xamarin team unfortunately issued a new version of Xamarin Forms for Android with massive performance issues.

Once a developer begins to familiarise themselves with the Forms architecture and progress is made, inevitably they will hit limitations when customising user interfaces or performance issues within certain platforms. The layout systems are designed to be very simplistic so that applications can be quickly scaffolded. If your user interface is more complex than a stack-based or linear layout, or if, for example, you need the UI components to react to a soft input such as an onscreen keyboard, you immediately lose the convenience of Forms.

The Ugly

Creating bespoke UIs in Xamarin Forms is extremely frustrating; in some cases it's almost impossible. Of course, depending on your design, compromises will be made throughout and designers will be left feeling like they first need to learn Forms in order to know what's possible before providing any specifications. A full native experience simply cannot be provided, only that which Forms has decided to expose. For example, Android popup menus provide a way to display a contextual menu in-situ for a button or similarly actionable view within the UI. However, since there exists no directly comparable Forms interface component, providing that common interaction pattern in your Forms Android app is only possible with the inclusion of a 'renderer'.

'Renderers' (and to a lesser extent 'effects') are Forms' way of exposing further customisation at a platform-specific level. At this point, a separate project would need to be added to the solution for each platform that requires customisation. Here, access to the native Xamarin platform APIs is trivial and construction of platform-specific interface components is possible. However, the additional abstraction of the renderer makes communication back to the main Forms project somewhat problematic.

Furthermore, it can be argued that renderers are more of a 'patch' for customisation than a solution. The renderer object is yet another Forms abstraction, rather than itself a platform-specific interface component. In short, while they allow a degree of customisation of the elements provided by Forms, they are still restricted in comparison to the fully native alternative. A project could easily find itself with a renderer for each screen, each performing a variety of customisations from small tweaks to larger scale redesigns. At this point it's clear to see that a native solution would be better suited.

Going Native

So what's the alternative? Xamarin native offers C# interfaces to the native platform APIs for each platform you wish to target. Nowadays, that isn't even limited to mobile but can also include a desktop counterpart through the Xamarin.Mac library. Matt's aforementioned article already covers a lot of the benefits of this approach but it's sufficient to say that code for aspects of your application such as models and business logic is easily shared between platforms. Of course Forms aims to reduce that code further but at a detriment to quality.

Developers already comfortable with iOS and/or Android development will feel somewhat at home in Xamarin native. Unlike Forms, all the standard components of each platform are available for use as usual, albeit written now in C#. It has to be stressed though that this is still very much native app development. Developers interact with the same APIs, utilise the same platform frameworks and build UIs in the same way they are used to. By combining the native development experience with build tools that produce native binaries specific to the platform, there is no cost to runtime performance while the paradigms of each platform are preserved.

Xamarin != Forms

If you find yourself asking "Should I use Xamarin Forms?" then the answer depends on your circumstances; it depends on your aims and prior experience but more often than not, the answer is no. As the CEO himself stated, Forms lends itself to very simple applications only. If you need a native app with some basic screens like a news feed and a contact page, for example, then Forms would be perfect. For any requirements beyond the most trivial, or to simply provide a user experience more fitting to each platform, opt for Xamarin native.

If you're interested in how we've used Xamarin native to build applications here at Instil check out our case study on 'Victor Go': a bespoke native video streaming application for iOS and Android. We're aiming to provide training for teams keen to leverage Xamarin native for building bespoke mobile applications so watch this space.

Article By
blog author

Niall Kelly

Principal Engineer