Xamarin Forms, with F#

xam-fsharp-01

I wanted to give F# a “go” in a Xamarin project, but Visual Studio (at least on Windows) does not have a Xamarin Forms template for F#. This means that I will need to create it myself.
I am sure it will be possible, and I will use a C# project as a guide.

I am in no way proficient in F#, but that is also because I have never really used it in a “real” project, and I would like to give it a good try.

In this post, I am going to attempt to create just the outline of the project.

Create a new project

In Visual Studio, I am creating an F#, .Net Standard Class Library. This will become my Xamarin Forms library (called PCL before .Net Standard). I am naming my project Jon.FXam.

I then want to add Xamarin.Forms from NuGet.

Now I need to create my App “Class”, I can’t find any XAML for F#, so I will just have to try my best at coding it.

Rename Library.fs to App.fs and set its content to:

namespace Jon.FXam

open Xamarin.Forms

type App() =
    inherit Application()

It builds.

Add an Android project

I am using Android because that is what I am most familiar with, and it is what I use most the time for projects at work. If I get the need to use iOS I will update this, or add to it. For now, it is Android only.

I use the Blank App (Android) Template, in F#. I name it Jon.FXam.Android. Some people might prefer to use .Droid but .Android seems to be the current convention.

I add Xamarin.Forms through NuGet, I also add a project reference to my base project. I then need to edit MainActivity.fs.

namespace Jon.FXam.Android

open Jon.FXam
open Android.App
open Xamarin.Forms
open Xamarin.Forms.Platform.Android

type Resources = Jon.FXam.Android.Resource

[<Activity (Label = "Jon.FXam.Android", MainLauncher = true, Icon = "@mipmap/icon")>]
type MainActivity () =
    inherit FormsAppCompatActivity()

    override this.OnCreate (bundle) =
        base.OnCreate (bundle)
        Forms.Init(this, bundle)
        this.LoadApplication(new App())

It builds.

AppCompat

Theme

App Compat needs a theme, so I copy the styles.xml file from another Xamarin project. This goes in Resources > values, and needs the build action set to AndroidResource.

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <style name="MainTheme" parent="MainTheme.Base">
  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--<item name="android:colorActivatedHighlight">#00f</item>-->
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated
         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
    <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>

    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
  </style>
  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
</resources>

MainActivity

The attributes on MainActivity need to reference the theme, so it gets changed to

[<Activity (Label = "Jon.FXam.Android", MainLauncher = true, Icon = "@mipmap/icon", Theme = "@style/MainTheme")>]

It builds.
It also runs, but at the moment it is only a blank screen.

Content Page

We are back to the Base Project.

I add New Item to the project, and select Source File. There is no XAML option. That is something I will miss, but even in a C# project, XAML is optional. I name it Page1.fs, and create a very basic outline of Xamarin Forms Page.

namespace Jon.FXam

open Xamarin.Forms

module private Page1 =
    let content () =
        let layout = new StackLayout()
        layout.Children.Add (new Label (Text = "Welcome to F# & Xamarin Forms!"))
        layout

type Page1() =
    inherit ContentPage (Content = Page1.content())


I do not know if this is the best way to do this (F# is not the first language for me), but it is working, so, for now, I am happy.

Then reference that from App.

type App () =
    inherit Application (MainPage = new Page1 ())

It builds.
It runs.
It shows something on the screen.

Follow up (XAML)

Visusal Studio for Mac has F# Xamarin projects (I am jelous). It also allows you to add XAML files to the project.

XAML File

Create an XML file in the Forms project, call it Page2.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Jon.FXam"
             x:Class="Jon.FXam.Page2">
    <Label Text="Welcome to F# &amp; Xamarin Forms, now with XAML!!!" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Be sure to add the full namespace in xmlns:local, and make sure you have the fully qualified class name in x:Class.

Code File

Create an F# file called Page2.xaml.fs

namespace Jon.FXam

open Xamarin.Forms
open Xamarin.Forms.Xaml

type Page2() =
   inherit ContentPage()
   let _ = base.LoadFromXaml(typeof<Page2>)

App

Set the application main page to Page, in App.fs

type App () =
    inherit Application (MainPage = new Page2 ())

This base XAML page can now be coppied if more XAML pages are needed.

Conclusion

This is the point that I was wanting to get to, and I am happy here. Happy that it can be done, and happy that I have a base project that I can clone and use as a starting point.

To peruse, copy, or make fun of any of the code, please find it on GitHub

Comments

Popular posts from this blog

Xamarin Forms, with F# - Part 2, ReactiveUI

Reactive Unit Testing