Combining F# and Xamarin Forms to Create Mobile Applications

While we certainly have been busy getting our hands dirty with Xamarin I’ve been doing some of my own. However, I’ve been messing around with using Xamarin with F#. I mentioned in a previous post that F# can be used very well for enterprise applications. Here’s an in depth look at F# with Xamarin for mobile applications.

But why F# with Xamarin, you ask? Well, it just turns out that I love working with both of these technologies and I got lucky that the awesome folks at Xamarin and Dave Thomas – who does most of the great work with F# for Xamarin – decided to take on F# as a first class language.

Before we get started, it’s helpful to remember that, in F#, if you reference any other part of your code, whether it’s in the same file or not, the part you are referencing needs to be defined before you reference it. More info can be found at the wonderful F# for Fun and Profit site.

Currently in Xamarin (at the time of this writing – version 5.9) there aren’t any actual Xamarin Forms or PCL templates. Though, it is rumored there will be more templates in 6.0.

FSharp-Solution

Using Xamarin Forms

Larry O’Brien already has a fantastic tutorial on how to use Xamarin Forms in an F# iOS or Android project. Though, I did notice that I didn’t have to bring in the FSharp.Core Mono delay signed NuGet package as F# is already included with Xamarin Studio. I just needed to bring in Xamarin.Forms from NuGet and add the following references from the Mono library as the post also describes:

  • System.ObjectModel.dll
  • System.Runtime.dll

After you have all that, you’re ready to roll with Xamarin Forms in F#.

To help understand a bit more of combining F# with Xamarin I ported the Phoneword application that we work with quite a bit in Xamarin University to F#. The results are the same if it was a C# project. This fairly simple app takes in a phone number and, if the number includes any letters, it translates the letters into the appropriate numbers and allows you to call that number.

Adding an F# PCL

Unfortunately, one of the things Xamarin Studio isn’t able to do yet (again, it’s definitely being worked on and will be out fairly soon) is the ability to add an F# Portable Class Library to the project. To do this you’ll have to open the solution up in Visual Studio and add it through there.

FSharpPCL

At this time, there seems to be an issue of opening this in Xamarin Studio (currently already being fixed), so I’ll continue using Visual Studio throughout the rest of this post.

For the most part I followed Larry O’Brien’s example from above. However, I did separate out the Xamarin Forms stuff from the AppDelegate file into the PCL project. With the very generous help from Dave Thomas, we were able to get a running sample all in F# and Xamarin Forms.

Here is the full Xamarin Forms code in F#.

[<Extension>]
type IListExtensions () =
    [<Extension>]
    static member inline AddRange(xs:'a IList, range) = range |> Seq.iter xs.Add

type IOpenUrlService =
    abstract member OpenUrl: string -> bool

type MainPage() =
    static member GetMainPage() =
       let contentPage = ContentPage(Padding = Thickness(20., Device.OnPlatform(40., 20., 20.), 20., 20.))
       let panel = StackLayout(VerticalOptions = LayoutOptions.FillAndExpand, 
                               HorizontalOptions = LayoutOptions.FillAndExpand, 
                               Orientation = StackOrientation.Vertical, 
                               Spacing = 15.)
       let phoneNumberText = Entry(Text = "1-855-XAMARIN")
       let translateButton = Button(Text = "Translate")
       let callButton = Button(Text = "Call", IsEnabled = false)</pre>
<pre><code>   translateButton.Clicked.Add(fun _ -&gt; callButton.Text &lt;- PhoneTranslator.toNumber phoneNumberText.Text
                                        callButton.IsEnabled &lt;- true)

   callButton.Clicked.Add(fun _ -&gt;
       let isCalling = contentPage.DisplayAlert(&quot;Dial a number&quot;, &quot;Would you like to call &quot; + phoneNumberText.Text, &quot;Yes&quot;, &quot;No&quot;).Result

       if isCalling then
         let dialer = DependencyService.Get&lt;IOpenUrlService&gt;()
         dialer.OpenUrl phoneNumberText.Text |&gt; ignore)

   panel.Children.AddRange([Label(Text = &quot;Enter a Phoneword:&quot;)
                            phoneNumberText
                            translateButton
                            callButton])

   contentPage.Content &lt;- panel
   contentPage
</code></pre>
<pre>type App() = inherit Application(MainPage = MainPage.GetMainPage()) 

The type IOpenUrlService there is to create our interface so we can use shared code in our Xamarin Forms page and implement it separately in each platform specific project. You may notice we call this lower down and use Xamarin Forms dependency service locator.

Also the string -> bool statement there simply states that the OpenUrl method takes in a string parameter and the return type is bool. Very similar to C#’s Func type where the last type in the signature represents the return type.

DependencyService.Get<IOpenUrlService>()
dialer.OpenUrl phoneNumberText.Text |> ignore

Note that we pipe into the built-in F# function ignore since we don’t need to do anything with the return type of dialer.OpenUrl at this point.

We also have to actually add our App that our MainPage will be set to. Surprisingly, this is very simple and concise. So much so that, you may have noticed, that it was just added to the end of our file that contains the MainPage.

type App() =
    inherit Application(MainPage = MainPage.GetMainPage)

As you can see, we can use Xamarin Forms just like we would use them in C#.

iOS

And in our AppDelegate for iOS we can do the same as if we were in a C# project.

[<assembly: Dependency(typeof<OpenUrlService>)>] do ()

[<Register("AppDelegate")>]
type AppDelegate() = 
    inherit FormsApplicationDelegate()</pre>
<pre><code>override val Window = null with get, set

// This method is invoked when the application is ready to run.
override this.FinishedLaunching(app, options) = 
    this.Window &lt;- new UIWindow(UIScreen.MainScreen.Bounds)
    Xamarin.Forms.Forms.Init()
    this.LoadApplication(App())
    base.FinishedLaunching(app, options)
</code></pre>
<pre>

With our iOS implementation of OpenUrlService.

type OpenUrlService() =
    interface IOpenUrlService with
        member this.OpenUrl url = UIApplication.SharedApplication.OpenUrl(new NSUrl("tel:" + url))

All we needed to include here is to set our dependency to let Xamarin Forms know where the platform specific code is, initialize Xamarin Forms, and tell it what application to load.

Android

Similar to iOS, we just have our MainActivity like we would in C# and we basically add the same from iOS.

[<assembly: Dependency(typeof<OpenUrlService>)>] do ()

[<Activity (Label = "PhoneWordFSharp.Droid", MainLauncher = true)>]
type MainActivity () =
    inherit FormsApplicationActivity ()</pre>
<pre><code>override this.OnCreate (bundle) =
    base.OnCreate (bundle)

    Forms.Init(this, bundle)

    this.LoadApplication(App())
</code></pre>
<pre>

With our Android implementation of OpenUrlService.

type OpenUrlService() =
    let isIntentAvailable (context:Context) (intent:Intent) = 
        let packageManager = context.PackageManager
        let list = packageManager.QueryIntentServices(intent, PM.PackageInfoFlags.Services).Union(packageManager.QueryIntentActivities(intent, PM.PackageInfoFlags.Activities))</pre>
<pre><code>    if list.Any() then true
    else false

interface IOpenUrlService with
    member this.OpenUrl url = 
        let context = Forms.Context
        let intent = new Intent(Intent.ActionCall)

        match context = null with
        | true -&gt; ()
        | false -&gt; intent.SetData(Uri.Parse(&quot;tel:&quot; + url)) |&gt; ignore

        isIntentAvailable context intent
</code></pre>
<pre>

This gives a brief introduction to using F# with Xamarin to make full mobile applications and without the need for using any C#. This will only get easier in the future so look out for updates to Xamarin Studio for all the good stuff.

The full code can be found on GitHub


Xamarin Partner

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?

Atmosera is thrilled to announce that we have been named GitHub AI Partner of the Year.

X