Building AppyLinks with Xamarin.Forms


This was a weekend project as my entry for the Xamarin Forms Evolve conference competition. …and I won first prize!


The new Xamarin.Forms release is pretty exciting. I spent a day exploring it and decided to build an app that I’ve personally seen a need for – quick way to get a list of links I may be working on to multiple devices. Day to day my team and I have to preview a lot of different (and long) urls on devices, for both when we’re building and when we’re presenting, so an app that can display a list of those links across devices would be quite handy! I decided to use a user’s GitHub gist as the data store since it allows for easy and continuous editing, and therefore authenticate the app using GitHub.

In the past, I’ve tried to use Xamarin Studio to create basic tools like this for both iOS and Android. Aside from some professionally-released apps, I’ve always stopped before having something coherent because I just could not get enough accomplished in a few hours – there was just too much overhead, and too much having to get to know the intricacies of each platform. The fact that I did get this done in a day, and that it did (for the most part!) ‘just work’ on both iOS and Android is proof that the new Xamarin.Forms is going to be incredibly useful. And this is only their first release…

AppyLinks lets you authenticate with github…

Logging in via GitHub

Logging in via GitHub

from where it will grab a gist named ‘AppyLinks’ and parse the basic list of links it expects…

List of links retrieved from a GitHub gist

List of links retrieved from a GitHub gist called ‘AppyLinks’

…Selecting any of the links will open a view with a browser navigated to the destination, and allow you to navigate back to the list.

Opening a link in a WebView

Opening a link in a WebView

Source code is public and available on GitHub at

The power of the new Xamarin.Forms

A typical view, which will render with native controls on iOS, Android and Windows Phone:

     <StackLayout Orientation="Vertical">
         <ActivityIndicator x:Name="listFetchingActivity" IsRunning="false" IsVisible="false"></ActivityIndicator>
         <ListView x:Name="urlView"
                   <TextCell Text="{Binding Title}" />

An interface to device-specific local-storage…

public interface IUserSettingsStore
    string GithubAuthorizationToken { get; set; }

…the implementation for android…

  public class UserSettingsStore : IUserSettingsStore
     //static control
     static AndroidSettingsStore preferencesInstance = null;
     public static void Init(Context settingsContext)
         //initialise preference store
         preferencesInstance = new AndroidSettingsStore(
             PreferenceManager.GetDefaultSharedPreferences (settingsContext)
     const string SETTINGSKEY_GITHUBAUTHTOKEN = "GithubAuthToken";
     //interface implementation
     public string GithubAuthorizationToken {
         get {
             return preferencesInstance.androidPreferences.GetString (SETTINGSKEY_GITHUBAUTHTOKEN, null);
         set {
             var editor = preferencesInstance.androidPreferences.Edit ();
             editor.PutString (SETTINGSKEY_GITHUBAUTHTOKEN, value);
             editor.Apply ();
     public UserSettingsStore ()

…and for iOS…

  public class UserSettingsStore : IUserSettingsStore
     const string SETTINGSKEY_GITHUBAUTHTOKEN = "GithubAuthToken";
     #region IUserSettingsStore implementation
     public string GithubAuthorizationToken {
         get {
             return NSUserDefaults.StandardUserDefaults.StringForKey (SETTINGSKEY_GITHUBAUTHTOKEN);
         set {
             NSUserDefaults.StandardUserDefaults.SetString (value, SETTINGSKEY_GITHUBAUTHTOKEN);
     public UserSettingsStore ()

Great things about Xamarin.Forms

  • You can make custom render implementations for each platform – for whole controls, or just to customise a small part of functionality – see the custom NavigationPageRenderer for iOS in AppyLinks source code.
  • You can provide Interfaces, and make an implementation on each platform, if you want to do platform-specific.
  • Each platform still has a separate project which can be completely customised or configured – Xamarin.Forms doesn’t enforce some kind of purist approach.

Challenges with v1

  • No designer, even though there’s both XAML support here, and there’s the nice new iOS designer with Xamarin. Because of the spaghetti c# view code, I daren’t add any (even basic) styling to these views with any speed, and that’s a shame (especially on android).
  • Xamarin Studio is having problems with intellisense and syntax highlighting for objects defined in XAML.
  • It’s an early release, so documentation is pretty bare, and also quite ambiguous at times.
  • There are currently some issues with System.Net.Http (probably affecting all mono uses, there’s a bug report from 2013 I commented on here).
  • Couldn’t get the XAML <FileImageSource /> element working, had to fallback to the Image.Source = ImageSource.FromFile pattern, which did work fine once you import the image file as a resource in to each platform-specific project.

With this new ability mixed with Portable Class Libraries (like you really can get to the stage where projects are 95% shared code, and the 5% platform-specific is finessing the details, rather than re-implementing the same logic!

Awesome logo designed by the lovely Kat Windley!

AppyLinks logo

AppyLinks Icon

2 thoughts on “Building AppyLinks with Xamarin.Forms

  1. @Anton – I have tried Freestyle, but it looks like you need to make custom renderers for any control you wish to custom-style when using Xamarin.Forms, unless someone has found an alternate solution.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s