So Xamarin released an update (v3) last week and it is truly a huge step forward for mobile developers. So if you are interested in cross-platform development and haven’t reviewed what Xamarin has done, then you need to stop what you’re doing and go look.
Xamarin is having a contest to showcase their new Xamarin.Forms functionality added to Xamarin 3. I spent the good part of last weekend reviewing everything that I could find regarding Xamarin.Forms and was in my chair coding by 7:00am Monday morning.
This is the story of what I created.
Introducing DrawIt
Imagine a cross-platform drawing tool. Yeah, I know, they probably exist but I didn’t let that get in my way. This is a very simple drawing application that allows you to draw with your finger, using a pen color of your choice.
Here is the iOS/iPad version:
The Android version:
The Windows Phone version:
Unfortunately, I was not able to get actual drawing mechanism working on WinPhone, so all we have at this point is the UI.
How it Works
I create a Xamarin.Forms shared-code project which created the following Visual Studio solution:
DrawIt is the shared-code project while the others exist to provide a platform-specific layer that the shared-code will reside upon.
Within the shared-code project, I started off with a custom class that inherited from Image that would allow me to specify a line color.
ImageWithTouch Class
public class ImageWithTouch : Image { public static readonly BindableProperty CurrentLineColorProperty = BindableProperty.Create ((ImageWithTouch w) => w.CurrentLineColor, Color.Default); public Color CurrentLineColor { get { return (Color)GetValue (CurrentLineColorProperty); } set { SetValue (CurrentLineColorProperty, value); } } }
Creating the User Interface
The best part of Xamarin.Forms is that I have a single codebase for the user interface, that looks something like this:
public MainPage() { Content = BuildGrid(); // Accomodate iPhone status bar. Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 10); } private Grid BuildGrid() { return new Grid { VerticalOptions = LayoutOptions.FillAndExpand, HorizontalOptions = LayoutOptions.FillAndExpand, RowDefinitions = { new RowDefinition { Height = GridLength.Auto }, new RowDefinition { Height = new GridLength (1, GridUnitType.Star) }, }, ColumnDefinitions = { new ColumnDefinition { Width = new GridLength (100, GridUnitType.Absolute) }, new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) }, }, Children = { {new Label { Text = "Draw It", Font = Font.BoldSystemFontOfSize (50), HorizontalOptions = LayoutOptions.CenterAndExpand, VerticalOptions = LayoutOptions.FillAndExpand }, 0, 2, 0, 1}, {BuildPalletFrame(), 0, 1}, {new ContentView { Content = BuildDrawingFrame(), Padding = new Thickness(10, 0, 0, 0), HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand }, 1, 1} } }; }
The UI elements exist within a fixed-size grid that is fitted to the screen for whatever device the application is running on.
All of the code you have seen so far is cross-device compatible and exists within a Shared project used by the device-specific projects
Custom Renderers
In order to provide the low-level drawing capabilities, I had to create what is called a custom-renderer for each of the device platforms. This is what actually creates the drawing surface for each device. Here is the renderer for iOS:
[assembly: ExportRenderer(typeof(ImageWithTouch), typeof(ImageWithTouchRenderer))] namespace DrawIt.iOS { public class ImageWithTouchRenderer : ImageRenderer { protected override void OnModelSet(VisualElement model) { base.OnModelSet(model); SetNativeControl(new DrawView(Control.Frame)); } protected override void OnHandlePropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnHandlePropertyChanged(sender, e); if (e.PropertyName == ImageWithTouch.CurrentLineColorProperty.PropertyName) { ((DrawView)Control).CurrentLineColor = ((ImageWithTouch)Model).CurrentLineColor.ToUIColor(); } } } }
The other two projects have similar renderers. The code that actually does the work is in a class called DrawView, which merely creates an ImageView that can be drawn upon using the native drawing mechanisms for the device.
Wrapping It Up
This was a fun little project and I barely touched the surface of what Xamarin.Forms can do. I am still rather shocked at the small amount of code that I had to write to get a standard user interface across all three platforms.
Drop me a line and let me know what you think.
Source
You can view my source on GitHub here: