Last year in May (2014), Xamarin announced the release of Xamarin 3. Part of this released included the announcment of Xamarin.Forms. The premise of Xamarin was that if you could program in .NET, you could build mobile apps for Android, iOS, and Windows Phone all at the same time with one single code base. No need to develop in Objective-C for your iOS app and Java for your Android app. However, despite doing things with one code base, you were still stuck doing some things on a per platform basis (albeit in C#), but more so you were stuck developing a separate User Interface for each platform. This also necessitated having a fairly decent understanding of each platform’s UI, lifecycle, etc idiosyncrasies. With Xamarin.Forms, you could either programmaticaly generate a UI or use XAML files to describe a User Interface. In either situation, that UI would then be generated specific to whatever platform you were running on. One example of this is the Tabbed Page. When it’s used in Xamarin.Forms, the tab bar shows up at the bottom on iOS and the top for Android and Windows Phone. Exactly as specified in the “standards of design” for each platform.
When first announced back in 2014, I decided that it was worth spending a bit more time with Xamarin and check out Forms. So I set out to build a project that would help my wife and I handle our budget. For almost three years, my wife have been using Google Sheets to track our budget. In fairly straightforward terms, we were able to set a weekly and monthly budget, record things by category, and see at any time how we were doing. If we were ever like ‘what did we spend so much money on during the week of June 23rd, 2014?” we could find that week and see each recorded purchase. The real issue was that recording expenses was a bit of a pain. Using a large Google Sheet on a mobile device (yes even running on Android) isn’t very fun. Add to that that fact that we make heavy use of notes within the sheet and that becomes even harder. So our expenses almost never got entered until I had time when we were at home some time later that day / week / month. What I wanted to do was build an Android and iOS app (I use Android and she uses iOS) to facilitate entry of data at any point in time from our phones in an easy manner. I didn’t want to do away with the Sheet we used so we could still view things easily from the browser, I just needed an easier to use viewing and entering mechanism for our phones. Once I figured out how to use Google Scripts to access and modify data in my sheet via an API (that wasn’t easy and in fact, it was a down right terrible experience…maybe I should write about that). So with Xamarin Forms I figured, it would be easy to build out an application that did what I wanted and would work on both Android and iOS.
The Original Issues
The dependencies for my first application were SUPER low. I needed to be able to authenticate the users against Google (I needed a valid identity that had been approved to use the Google Scripts that were essentially functioning as the Web API for my Google Sheet). Then I just needed to be able to make HTTP requests against that API and display the results / allow users to enter new data. Considering the fact that the way our budget works is that there are only 5 or so categories for expenses, even for a full month, we’re only dealing with a maximum of 5 rows of data. All in all there were only 3 important pages in the app: a splash screen, a page displaying a specific month’s data, and a page to display the data for a specific week including it’s individual transactions.
Instantly I started running into cases where the “truly one code base” idea didn’t pan out. First for authentication, in order to pop open a web view to do OAuth against Google, I needed to create code specific to Android and iOS to handle generating that view and either handle it as an Activity (Android) or present it as a View Controller (iOS). Not really the end of the world but a bit of an annoyance since Auth across platforms should be easier (and there is a component but it wasn’t working for me here and still had issues in my latest work). The same was true for simple things like showing a dialog box or a toast message to the user. In fact, there were still quite a few areas where I ended up doing things in Interface classes so I could implement platform specific functionality (toast, dialogs, user preferences / storage, auth, etc).
The next issue was mildly more serious. The same User Interface generated for iOS and for Android were different beyond what was expected. After logging in, the user is presented with a screen to create a PIN code for easier security the next time the app starts. On Android, when the user taps a number, it causes an asterisk to show up in one of the PIN code text boxes. The exact same code running on iOS and nothing appeared. Furthermore, the same text boxes on iOS change size after you tap a number (causing Text to supposedly appear in a text box). This sort of inconsistency is just weird. At this point, you’re left needing to create different UI settings per platform (though I think that was enormously complicated at that point in Xamarin.Forms evolution). This issue manifested itself in several other places. I did what I think was a decent job looking around for a good solution but was left wanting. At the end of the day, the app was only being used by two people and it wasn’t worth the time trying to get things to look great.
More recently, I was working with several people on a proof of concept IoT solution. My task was to build the mobile app piece of the puzzle. We wanted functionality for Android, iOS, and Windows Phone so I started building a Xamarin app. This was over a year since my previous experience with Xamarin.Forms and I’d been assured by a few people that use Xamarin on a daily basis that things had improved. Happily, I can report that that is somewhat true. One easy example of this is popups. Xamarin has added the ability to use DisplayAlert and DisplayActionSheet to provide native pop-ups / toasts / dialogs on each platform. Additionally, they’ve greatly cleaned up their guidance for using Custom Renderers for when you do need to specify a UI on each platform (in addition to adding OnPlatform settings to XAML so you can specify different attributes per platform). But sadly, there are still quite a few issues.
- In order to do some of the things I wanted to do with the toolbars, I had to do per platform things. For example in order to add a button to the right side of the toolbar, I ndeded to clear ToolbarItems before adding the button on Android but not elsewhere.
- There still isn’t an easy to use Authentication component. I had to use the Custom Renderers to get this to work despite the same thing really happening on every platform.
- Navigation code is very different in the Windows Phone version (you have to get the RootVisual and Navigate to the Auth UI which causes issue when you want to navigate to other parts of the app).
- The above issue with navigation in Windows Phone made me find an additional issue where one page would be transparent and you’d see through to pages behind it. I ended up having to explicitly set a background color on each and every page.
- I was able to set background color in the Xaml using a ResourceDictionary and OnPlatform and then using that setting as the BackgroundColor attribute for StackLayouts, but I have to believe there is a better way to handle this then doing it for each platform whenever you want to do a setting like that.
- Adding dependencies / NuGet packages / Components is still a confusing mess. Am I adding this to each projet? Am I adding it to the shared code project? Why am I getting an error about my project targeting portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10?
- In order to get the MasterDetail layout, I had to do what felt like a weird amount of code as opposed to specifying the layout in XAML.
I still think, and will continue to tell people that there are great scenarios where Xamarin is either the right decision or something that should be seriously considered. This time I was building a POC and the actual functionality of the app itself was easy to accomplish across the three platforms. It was the stuff that seems like it would be simple (authenticating, navigating, accessing code libraries) that is still a pain. If I had to choose between spending the time overcoming these hiccups (and writing some platform specific code), or building everything natively, I’d still strongly consider Xamarin. For now though, it’s definitely still a matter of Write once, painfully debug everywhere.