I came across Xamarin Forms soon after developing for Xamarin, it was an early version of Forms and was, let’s say, basic. Apart from very simple internal apps or prototypes it wasn’t much use and reminded me of other cross platform solutions…poor.
However as more releases were made it improved (its currently on Xamarin Forms 2.3.x) but when deciding with a client how to build something, and discussing all the options pure native, Xamarin or Xamarin Forms, I usually steered them away from Xamarin Forms.
I then started working for a client who had built one of their apps using it and ended up maintaining it. It was built with 100% XAML UI, something I wasn’t really familiar with but after some time became fairly proficient with, and in doing so learnt lots of new techniques, although as it wasn’t compiled I was caught out quite a few times by typos in XAML code and obscure exceptions being thrown.
We were then hired by a startup to build their iOS and Android apps, remit was rapid dev in both iOS & Android simultaneously, server was REST API based and it was customer facing and there were some early screen designs. If we could build the UI in Xamarin Forms I thought it was worth a try, so quickly set about prototyping some of the designs and Forms handled them well.
I carefully explained the downside to using Forms, for example there may be some compromise on UI, luckily I knew the UX/Designer very well and was sure we could work through most UI issues if and when they arose.
The customer in this case was Jobhawk, a recruitment service for the construction industry, both iOS and Android apps were available at launch, the initial build time for both apps was 3-4 months with a single developer.
Although now fairly familiar with XAML (and can see the advantage of XAML with your UI being clearly defined in XML), I found trying to do everything in XAML took me longer as it wasn’t the way I was used to developing and this client was against the clock. I could have gone either way but decided to stick with what I knew best, code, so the UI was built in C#, adding all the binding at the code level.
Autofac, for no other reason than I had used it before and therefore felt familiar with it.
After some persuading I managed to get the server dev to supply the swagger file to document the REST API, this was a bit fiddly and not well documented itself, but once it was done it could be used to generate the client library using AutoRest (there was no automated service for Netty they used). Once we had this process defined it was plain sailing, with any change made to REST API contracts resulting in a new swagger file being provided, and I had a 1 line script to run to re-generate the client.
As soon as we had AutoRest working we created a local mock implementation of the client generated by AutoRest which can be injected into the apps, each REST API call being used in the app returns a canned set of objects, that evolved into an in-memory data set to test editing of data. The mock was used for unit testing and developing the UI. It is so much easier developing a complicated UI if you can mock all the API calls and provide realistic test data and not rely on real REST api calls and test objects added on the actual server which may just be empty data or non functional end points until the server backend is completed.
If you invest in any bit of software, invest in Charles Proxy. Once you move onto the real REST api, Charles is invaluable in tracing all the REST requests and responses; allowing you to intercept and breakpoint api calls, along with injecting responses and Status code results etc.
Nearly all common code was added into the main PCL project. Including business logic, UI, services, providers, models, view models, caching, commands.
Any code depending on build parameters requires a common Shared DLL project that will be built for the target platform (rather than PCL), it’s usually pretty lightweight compared to the PCL.
Simple caching of the REST calls was built around Akavache, storing json collections using key pairs. Some of the calls into the PCL were even pre-cached as they changed rarely.
Unit tests were built with Moq against the Mock implementation of the client.
Although not a visual app there was a lot of iconography, particularly trades that appear throughout the app, building them for all screen resolutions, in different sizes depending on use for both platforms would be a huge pain, so decided to try the SVG route, something I hadn’t used since Symbian days, there was a library available Xamarin Forms Plugin Library that supported SVG’s, but it wasn’t kept up to date, so I did what others suggested on forums and rolled our own based on code found there and using NGraphics as the SVG parser. The project UI designer and I learnt a few things on the way to make this process smoother, like what not to export into the SVG, and even wrote an app that loaded all the SVG’s in the PCL into a ViewController to easily test them. All the actual SVG assets were added into the main PCL as EmbeddedResources. There were only a few assets that could not be supplied this way, apart from icons and splash screens of course, but also burger menu and tab icons.
Client requested from day one that the app should be easy to localise, so a localisation project was added to the solution using a RESX file, which made it easy to maintain and added only a very small overhead in developing. Using a RESX XML file for all the language resource strings also meant the file could be given to translators directly to work with.
Xamarin Plugin’s and nugets
There are various Xamarin Plugins available that make developing cross platform much easier, always check if what you need isn’t already available as a plugin.
We used :-
Autorest – Generates REST client library for comms with server from YAML
Xam.Plugin.Connectivity – Data connectivity availability api
Akavache – Keypair caching using SQLLite.
Xam.Forms.CarouselView – Cool component for doing native like carousel view in forms.
Xam.Plugin.DeviceInfo – Information about the device app is running on, i.e. iOS version, phone, model etc
Xam.Plugins.Settings – Persistent local storage using key pair
Xam.Plugins.Messaging – Creating SMS’s using native built in UI.
Plugin.Share – Sharing links to various social media using platforms built in share menus.
Xamarin.Firebase.iOS.CloudMessaging – PNS using GCM for iOS
Xamarin.Firebase.Messaging – PNS using GCM for Android
Xamarin.FFImageLoading – Added after initial release for loading thumbnail images from remote URL’s in cells. Great performance, and much more reliable than built in alternatives.
But what is the compromise?
We did have to make some compromises. The designer asked for lists with cells with variable heights, that expanded and closed on tapping, I tried this, but just couldn’t get it to work nicely, especially on iOS, android was OK. So we compromised on opening a detailed view. The client was fine with this.
- Bundle Size – The bundle sizes are much larger than native apps, but only an issue when downloading over data networks.
- UI – Compromises will probably need to be made on UI, so an understanding UX, design and product teams are essential.
- Single language
- Single UI
- Single IDE
- Shared unit tests
- Rapid development on both platforms simultaneously.
There is always a trade off. As mentioned before, the pitfalls of using Xamarin Forms are if your objective is to make one of the most beautiful apps in the AppStore with lots of custom animations & interactions, if so, then Forms is not for you, stick with pure Xamarin Native and develop the UI for each platform separately.
However if functionality and rapid development is your aim then consider Xamarin Forms – get the product owner and designer on board and explain the trade offs, do what I did and prototype some of your key screens to show the customer and designer. If you find a key screen difficult, don’t rule it out yet, if 95% of the app is simple, but one screen needs to be custom, still consider building using Forms but build that screen natively with a custom renderer. For example I am currently building an app for another client where most of the screens are simple, but one screen is a map with lots of interactions. There is a map plugin in forms, but it is basic and simply enables pins on a map (fixed colour). For this new app the customer wants a very rich maps experience so we chose the map plug in carefully for each platform and then built custom renderers, giving a great native maps experience whilst still using and gaining all the advantages of Xamarin Forms.