Add custom tiles to map in Xamarin Forms

If we want to use other maps than the platforms default in our apps we need to provide tiles to the map view. To do that we need to create a custom renderer per platform.

iOS
In iOS we need to create an url template that contains {x}, {y} and {z}. Those be replaced with values from the map engine.

protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
    if(e.NewElement != null)
    {
        var map = (MKMapView)Control;
 
        var urlTemplate = "https://urltomaptiles/{x}/{y}/{z}";
        var tileOverlay = new MKTileOverlay(urlTemplate);
 
        map.OverlayRenderer = OverlayRenderer;
 
        map.AddOverlay(tileOverlay);
    }
}
private MKOverlayRenderer RenderOverlay(MKMapView mapView, IMKOverlay overlay)
{
    var tileOverlay = overlay as MKTileOverlay;
 
    if(tileOverlay != null)
    {
         return new MKTileOverlayRenderer(tileOverlay);
    }
 
    return new MKOverlayRenderer(overlay);
}

If we are getting tiles from a service that not supporting the url format with x-,y- and z value we can customize the url. To do that we need to subclass MKTileOverlay and override the URLForTilePath method. In that method we will write the code that created the url. I recommend to create a helper class for that so we can reuse it on the other platforms.

public class CustomTileOverlay : MKTileOverlay
{
     public override void LoadTileAtPath(MKTileOverlayPath path, MKTileOverlayLoadTileCompletionHandler result)
     {
         base.LoadTileAtPath(path, result);
     }
 
     public override NSUrl URLForTilePath(MKTileOverlayPath path)
     {
         //Here we write the code for creating the url.
         var url = MapHelper.CreateTileUrl((int)path.X, (int)path.Y, (int)path.Z);
 
         return new NSUrl(url);
     }
}

Instead of creating a MKTileOverlay we will create a CustomTileOverlay and add it to the map.

map.AddOverlay(new CustomTileOverlay());

Android
Except to subclass MapRenderer we also need to implement the IOnMapReadyCallback interface. The method OnMapReady will handle when the GoogleMap object is ready so we can work with it. But first we need to request the GoogleMap object in the override of the OnElementChanged method.

public class ExtendedMapRenderer : MapRenderer, IOnMapReadyCallback
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);
 
        if(e.NewElement != null)
        {
            ((MapView)Control).GetMapAsync(this);    
        }
    }
 
    public void OnMapReady(GoogleMap googleMap)
    { 
        var options = new TileOverlayOptions();
        options.InvokeTileProvider(new CustomTileProvider());
        googleMap.AddTileOverlay(options);
    }
}

In Android we always need to create an own tile provider.

public class CustomTileProvider : UrlTileProvider
{
    public CustomTileProvider() : base(256,256) {}
 
    public override URL GetTileUrl(int x, int y, int zoom)
    {
        //Here we write the code for creating the url.
        var url = MapHelper.CreateTileUrl(x, y, zoom);
 
        return new URL(url);
    }
}

UWP (Windows 10)
As in iOS, UWP using an url that contains {x},{y} and {z} that will be replaced by the map engine.

protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
    base.OnElementChanged(e);
 
    if (e.NewElement != null)
    {
        map = Control as MapControl;
 
        HttpMapTileDataSource dataSource = new HttpMapTileDataSource("https://urltomaptiles/{x}/{y}/{z}");      
        MapTileSource tileSource = new MapTileSource(dataSource);
        map.TileSources.Add(tileSource);
 
     }
}

If we want to modify the url we using the UriRequested event on HttpMapTileDataSource.

HttpMapTileDataSource dataSource = new HttpMapTileDataSource();
dataSource.UriRequested += DataSource_UriRequested;

The code for modifying the url is placed in the event handler.

private void DataSource_UriRequested(HttpMapTileDataSource sender, MapTileUriRequestedEventArgs args)
{
    var deferral = args.Request.GetDeferral();
 
    //Here we write the code for creating the url.
    var url = MapHelper.CreateTileUrl(args.X, args.Y, args.ZoomLevel);
    args.Request.Uri = new Uri(url);
 
    deferral.Complete();
}

MvvmLight Navigation Extension

When navigating in iOS we can choose to do a modal navigation. That means that we open a page that is on top of the other pages and not included in the navigation stack. When using MvvmLight we only have one method (NavigateTo) when we want to open a new page.

While I want to use MvvmLight and open “modals” I have created a MvvmLight extension for iOS (for storyboards only in this pre version) and Android, https://www.nuget.org/packages/MvvmLightNavigationServiceExtension. If you’re interested in the source, it will be at GitHub, https://github.com/dhindrik/MvvmLightNavigationExtension.

While this is a pre release, feedback is very welcome!

Using the extension from shared code
To use it in your ViewModels you need to add the namespace to the class.

using MvvmLightNavigationExtension;
var navigation = ServiceLocator.Current.GetInstance();
navigation.OpenModal("Page2");

Setup
We will configure the NavigationService in same way as when we using NavigationService from MvvmLight but we using NavigationServiceExtension() instead of NavigationService and our instance of NavigationServiceExtension should be registered to both INavigationService and INavigationServiceExtension.

iOS:

 var nav = new MvvmLightNavigationExtension.iOS.NavigationServiceExtension();
 nav.Initialize((UINavigationController)Window.RootViewController);
 nav.Configure("Page1", "MainView");
 nav.Configure("Page2", "PageView");
 
container.RegisterInstance(nav);
container.RegisterInstance(nav);

Android:

 var nav = new MvvmLightNavigationExtension.Droid.NavigationServiceExtension();
 nav.Initialize():
 nav.Configure("Page1", "MainView");
 nav.Configure("Page2", "PageView");
 
container.RegisterInstance(nav);
container.RegisterInstance(nav);

Use MvvmLight in Xamarin.iOS

I think MVVM is a good design pattern to separate UI and business logic. MvvmLight is one of the most popular frameworks for MVVM. In this blog post I will show how you can use MvvmLight when we’re building a iOS app with Xamarin.

The fist step is to create a view model. I always have my view models in a PCL (Portable Class Library) so I can share the view models with other platforms, Android and Windows for example.

When I have created a new project I will install MvvmLight to it. The easiest way to do that is to install the NuGet package for MvvmLight. The package should be added to both the PCL project and the iOS project.

Install-package MvvmLightLibs

When we are working with MVVM all ViewModels need to implement the INotifyPropertyChanged interface. INotifyPropertyChanged has one event handler, PropertyChanged that we have to implement. When using MvvmLight this is done in a base class called ViewModelBase.

In my example the viewmodel

public class MainViewModel : ViewModelBase
{
        private string _name;
 
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
 
        public RelayCommand Send
        {
            get
            {
                return new RelayCommand(() =>
                {
                    var nav = ServiceLocator.Current.GetInstance<INavigationService>();
                    nav.NavigateTo(Views.Hello.ToString(), Name);  
                });
            }
        }
}

Navigation

MvvmLight has a INavigationService interface that uses for navigation and each platform will have their own implementation. On iOS you need to create a NavigationService and configure it in the AppDelegate class.

var nav = new NavigationService();
nav.Initialize((UINavigationController)Window.RootViewController);
nav.Configure(Views.Main.ToString(), "MainView");
nav.Configure(Views.Hello.ToString(), "HelloViewController");

In my example I using Autofac for IoC, we can also use the IoC container that is in the MvvmLight package. When we have created the NavigationService we had to register it in the IoC container as a INavigationService.

var builder = new ContainerBuilder();
builder.RegisterInstance<INavigationService>(nav);
 
builder.RegisterType<MainViewModel>();
builder.RegisterType<HelloViewModel>();
 
var container = builder.Build();
 
var serviceLocator = new AutofacServiceLocator(container);
 
ServiceLocator.SetLocatorProvider(() => serviceLocator);

If you’re using storyboards you have to use the Configure(string key, string storyboardId) method. The key is just a key that we set to the view, we will use that key when we will navigate to the view. (See the code fore the ViewModel above. StoryboardId is a property that we’re setting in the storyboard designer.

Properties

Data bindings

When using MVVM we want to use data bindings. In iOS we have to create the bindnings in code. MvvmLight will help us with that. In the class for the UIViewController we hade to add a using to the MvvmLight helpers.

using GalaSoft.MvvmLight.Helpers;

The MvvmLight helper namespace will contains the extension methods SetBinding and SetCommand.

When binding to a UITextField we can set which event who will trigger an update of the our ViewModel with the method UpdateSourceTrigger. WhenSourceChange is used to set which property in the ViewModel who will be updated.

The SetCommand method’s first argument will be which event that will execute the command.

public override void ViewDidLoad()
{
            base.ViewDidLoad();
 
           //Creates a binding to a UILabel
            this.SetBinding(() => ViewModel.Name, () => MyLabel.Text);
 
           //Creates a binding to a UITextField
            this.SetBinding(() => Name.Text).
                UpdateSourceTrigger("EditingChanged").
                WhenSourceChanges(() => ViewModel.Name = MyTextField.Text);
 
            //Binding a command to the Button.
            MyButton.SetCommand("TouchUpInside", ViewModel.Send);
}

The complete code for this sample is on GitHub, https://github.com/dhindrik/XamarinMvvmLightSample

How to succeed with Xamarin.Forms

Xamarin.Forms makes it possible to write UI for all the major mobile platforms, iOS, Android and Windows Phone with one shared code base. Many developers think that Xamarin.Forms isn’t is good enough to create apps that will be published and they think Xamarin.Forms is more a tool for prototyping.

If you think Xamarin.Forms is a “magic” product that will fix everything, you will properly not succeed with Xamarin.Forms. For me Xamarin.Forms is a framework that helps me build apps for multiple platforms. If you look at Xamarin.Forms in that way you will increase your chances to success with Xamarin.Forms.

Xamarin.Forms is delivered with a lot of controls that uses the Xamarin.Forms framework to render native platform specific controls. A Xamarin.Forms control is in many way just a description of what the control can do. From that description is native controls rendered.

The power of Xamarin.Forms is that you can use the framework to create you own renderers if you want to renderer a control different then the standard renderer. You can also create your own controls by using custom renderers.

I guess one of the most common issues with Xamarin.Forms i ListView performance. It’s not surprising, you maybe have 5 or 6 controls for each cell (row). If cells are reused you might have 8 cells. It means that forms need to create at least 40 renderer objects. And if any of the controls is a StackLayout or a RelativeLayout where it’s render has do to a lot of calculations where to place controls I guess you will realize that it will use a lot of memory.

So if you instead create your own custom cell that has it own renderer, there will be only one renderer for each row or if you write a renderer for the whole list you will only have one renderer. Can you realize how much memory you will save on that? If not you will see it when you are scrolling in your ListView,

The biggest problem when using Xamarin.Forms is that the developers don’t know how Xamarin.Forms works and they don’t know much about the target platforms. If you want to create a excellent app with Xamarin.Forms you still need to have knowledge about the target platforms.

Now you maybe want to ask me why you should use Xamarin.Forms? The answer is that even if you have to write platform specific code for some views there are still much you can use of the controls that is delivered with Xamarin.Forms out of the box and the powerful Xamarin.Forms framework makes it possible to write platform specific code when what you get out of the box with Xamarin.Forms not is enough.

My recommendation is to so do as much as possible with what you get out of the box with forms and don’t care about performance and if it doesn’t look perfect from the beginning. When you have created your app and built all the business logic, then you can start to look at how to make the app perfect. Than you can start write platform specific code to get better performance and a better look of the app.

TechDays 2015

Den 20 oktober börjar TechDays med förkonferens, jag och Johan Karlsson kommer att dela med oss av våra kunskapar gällande cross-platformutveckling.

Att bygga cross-platformlösningar är alltid en stor utmaning då det i grunden är olika operativsystem, programmeringsspråk och utvecklingsmiljöer.
Xamarin löser en stor del av cross platform problematiken genom att man kan utveckla appar för iOS, OSX och Android med C#. iOS och Android kan även byggas i Visual Studio. Under dagen kommer vi gå genom hur man bygger arkitektur och gränssnitt för en optimal native upplevelse på varje plattform, det vill säga iOS, OSX, Android och Windows. Vi kommer också att visa hur man kan testa mobila applikationer på ett effektivt sätt med hjälp av Xamarin TestCloud.

Läse mer här, http://tdswe.kistamassan.se/Program-2015/Sessioner/Pre-Conf-Cross-Platform-pa-ratt-satt

iOS range slider for Xamarin and Xamarin.Forms

In this post I will show you how to build a range slider for Xamarin.iOS and how to write a custom renderer if you want to use it with Xamarin.Forms. If you want to use the range slider control you can write the code yourself or use the flipper forms control library, https://github.com/johankson/flipper, that can be installed from NuGet, https://www.nuget.org/packages/Flipper.Forms/. On GitHub you will also find a sample app that using the control.


iOS Range Slider

The control will be built up of six UIViews, one for the slider background, two for the indicators, two transparent views to increase the touch area for the indicators and one for the range between the indicators. The first step is to create a new class that inherits from UIView. In the constructor of the new class we are creating the views and adding them to the view. On the both indicators we’re adding a UIPanGestureRecognizer so we can detect when the users dragging the indicator.

public class RangeSlider : UIView
{
    private UIView _background, _leftIndicator, _rightIndicator, _range, _leftTouchArea, _rightTouchArena;
        private UIPanGestureRecognizer _leftIndicatorGesture, _rightIndicatorGesture;
 
     public RangeSlider()
     {
            _background = new UIView();
            _background.BackgroundColor = UIColor.LightGray;
 
            _range = new UIView();
            _range.BackgroundColor = UIColor.Blue;
 
            _leftIndicator = CreateIndicator();
            _leftIndicatorGesture = new UIPanGestureRecognizer(OnPan);
 
            _rightIndicator = CreateIndicator();
            _rightIndicatorGesture = new UIPanGestureRecognizer(OnPan);
 
            _leftTouchArea = new UIView();
            _leftTouchArea.BackgroundColor = UIColor.Clear;
            _leftTouchArea.AddGestureRecognizer(_leftIndicatorGesture);
 
            _rightTouchArena = new UIView();
            _rightTouchArena.BackgroundColor = UIColor.Clear;
            _rightTouchArena.AddGestureRecognizer(_rightIndicatorGesture);
 
            AddSubview(_background);
            AddSubview(_range);
            AddSubview(_leftIndicator);
            AddSubview(_rightIndicator);
            AddSubview(_leftTouchArea);
            AddSubview(_rightTouchArena);     
     }
 
     private UIView CreateIndicator()
     {
            var indicator = new UIView()
            {
                   BackgroundColor = UIColor.Gray
            };
 
            indicator.Layer.CornerRadius = 10;
            indicator.Layer.MasksToBounds = true;
 
            return indicator;
      }
}

Then we need to layout our views, we will do that in an override of the LayoutSubviews method. We also need to check if the views already is layouted so the layout not will be restored to the start layout if the method runs again.

private bool _layouted;
public override void LayoutSubviews()
{
      base.LayoutSubviews();
 
      if (!_layouted)
      {
            _background.Frame = new RectangleF(0, 19, (float)Frame.Width-20, 2);
            _range.Frame = new RectangleF(0, 19, (float)Frame.Width-20, 2);
            _leftIndicator.Frame = new RectangleF(0, 10, 20, 20);
            _rightIndicator.Frame = new RectangleF((float)Frame.Width - 40, 10, 20, 20);
 
            _leftTouchArea.Frame = new RectangleF(0, 0, 40, 40);
            _rightTouchArena.Frame = new RectangleF((float)Frame.Width - 60, 0, 40, 40);
 
            _layouted = true;
       }
}

In the OnPan method we want to update the position of the indicators if state of the gesture recognizer is began or changed. For this range slider we want the indicator to move in steps. To do this we need to move the indicator to next step if we have started to slide from the previous step. For that we need to know the step length in pixels and the cumulative manipulation and the delta manipulation. To calculate cumulative manipulation we need to save the position of the indicator when we starting the manipulation.

While you moving the indicator to next step when it has passed the previous you will have to check if the cumulative manipulation has passed the current step before you moving the indicator to next step.

 private void OnPan(UIPanGestureRecognizer recognizer)
        {
            if (recognizer.State == UIGestureRecognizerState.Began || recognizer.State == UIGestureRecognizerState.Changed)
            {
                var stepLength = _background.Frame.Width / ((MaxValue - MinValue) / Step);
 
                var touchPoint = recognizer.LocationInView(this);
 
                UIView indicator = null;
                UIView touchArea = null;
 
                //Is this a slide to left or right?
                if (recognizer == _leftIndicatorGesture)
                {
                    indicator = _leftIndicator;
                    touchArea = _leftTouchArea;
                }
                else if (recognizer == _rightIndicatorGesture)
                {
                    indicator = _rightIndicator;
                    touchArea = _rightTouchArena;
                }
 
                //save the start position for use when calculating cumulative manipulation
                if (recognizer.State == UIGestureRecognizerState.Began)
                {
                    _startX = (float)indicator.Center.X;
                }
 
 
                var cumulativeManipulation = touchPoint.X - _startX;
                var deltaManipulation = touchPoint.X - indicator.Center.X;
 
                //Check if the cumulative manipulation is has passed the last step
                if (deltaManipulation > 0 && cumulativeManipulation / stepLength > _lastStep ||
                    deltaManipulation < 0 && cumulativeManipulation / stepLength < _lastStep)
                {
                    if (deltaManipulation > 0)
                    {
                        _lastStep++;
                    }
                    else
                    {
                        _lastStep--;
                    }
 
                    //Calculate the new position of the indicator
                    var numberOfSteps = Math.Ceiling(deltaManipulation / stepLength);
                    var newPosition = new CGPoint(indicator.Center.X + stepLength * numberOfSteps, indicator.Center.Y);
 
                    var pixelStep = (MaxValue - MinValue) / Frame.Width;
 
                    if (touchPoint.X >= 0 && touchPoint.X <= _background.Frame.Width-10)
                    {
 
 
                        if (recognizer == _leftIndicatorGesture)
                        {
 
                            var newLeftValue = Round(MinValue + (pixelStep * newPosition.X));
 
                            if (newLeftValue >= RightValue)
                            {
                                return;
                            }
                        }
                        else if (recognizer == _rightIndicatorGesture)
                        {
                            var newRightValue = Round(MinValue + (pixelStep * newPosition.X));
 
                            if (newRightValue <= LeftValue)
                            {
                                return;
                            }
                        }
 
 
                        if (recognizer == _leftIndicatorGesture)
                        {
                            indicator.Center = newPosition;
                            touchArea.Center = newPosition;
                            var width = _rightIndicator.Center.X - _leftIndicator.Center.X;
                            _range.Frame = new CoreGraphics.CGRect(newPosition.X, _range.Frame.Y, width, _range.Frame.Height);
                        }
                        else if (recognizer == _rightIndicatorGesture)
                        {
                            indicator.Center = newPosition;
                            touchArea.Center = newPosition;
                            var width = _rightIndicator.Center.X - _leftIndicator.Center.X;
                            _range.Frame = new CoreGraphics.CGRect(_range.Frame.X, _range.Frame.Y, width, _range.Frame.Height);
                        }
 
 
 
                        LeftValue = Round(MinValue + (pixelStep * _leftIndicator.Center.X));
                        RightValue = Round(MinValue + (pixelStep * _rightIndicator.Center.X));
 
                        if (ValueChanging != null)
                        {
                            ValueChanging(this, new EventArgs());
                        }
                    }
                }
            }
            else if (recognizer.State == UIGestureRecognizerState.Ended)
            {
                if (ValueChanged != null)
                {
                    ValueChanged(this, new EventArgs());
                }
 
                _lastStep = 0;
            }
        }

I have added to events to the slider, ValueChanging and ValueChanged. ValueChanging occurs during the manipulation of the range slider and ValueChanged when the manipulation is finished. This because you maybe want to update labels with the values of the range slider during manipulation and update data based on the range slider when the manipulation is completed.

We also want to make it possible to set start values for the indicators. To do that we are creating a method called UpdateValue. We call the method from LayoutSubviews and from the setters of LeftValue and RightValue. It is important that the code not is running after that we have started using the slider. Therefore we have surrounded the call to the method with an if-statment. The code will run if a initialized variable is false, we will set it to true in the OnPan method.

private void UpdateValue(UIView indicator, UIView touchArea, double value)
{
            var percent = value / (MaxValue - MinValue);
 
            var position = (double)(_background.Frame.Width * percent);
 
            if (!double.IsNaN(position))
            {
                indicator.Center = new CGPoint(position, indicator.Center.Y);
                touchArea.Center = new CGPoint(position, indicator.Center.Y);
 
                var width = _rightIndicator.Center.X - _leftIndicator.Center.X;
                _range.Frame = new CoreGraphics.CGRect(_leftIndicator.Center.X, _range.Frame.Y, width, _range.Frame.Height);
 
                if (ValueChanged != null)
                {
                    ValueChanged(this, new EventArgs()); 
                }
            }
}

Xamarin.Forms
If you want to use the control with Xamarin.Forms you need to create a Xamarin.Forms control and a custom renderer. The Xamarin.Forms control will inherit from View and it will contains all the properties of the range slider, no logic at all.

 public class RangeSliderRenderer : ViewRenderer<Flipper.Controls.RangeSlider, iOS.Controls.RangeSlider>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<RangeSlider> e)
        {
            base.OnElementChanged(e);
 
            if (e.NewElement != null)
            {
                var slider = new Controls.RangeSlider();
                slider.Frame = new CGRect((float)Frame.X, (float)Frame.Y, (float)Frame.Width, 200);
 
                slider.ValueChanging += slider_ValueChanging;
                slider.ValueChanged += slider_ValueChanged;              
 
                SetNativeControl(slider); 
            }
 
        }
 
        void slider_ValueChanged(object sender, EventArgs e)
        {
           if(Element.Command != null && Element.Command.CanExecute(null))
           {
               Element.Command.Execute(null);
           }
 
           Element.NotifyValueChanged();
        }
 
        void slider_ValueChanging(object sender, EventArgs e)
        {
            Element.LeftValue = (float)Control.LeftValue;
            Element.RightValue = (float)Control.RightValue;
        }

The complete code can be found at GitHub, https://github.com/johankson/flipper

Xamarin.Forms and iOS segemented control

A common control in many iOS apps is the segmented control. Xamarin.Forms has no support for the segemented control out of the box. This blog post will show you how to create a control in Xamarin.Forms that is mapped to UISegmentedControl in iOS.

In my sample I have named the control, FilterControl because is often used as a filter control and if you write a implementation of the control on the other platforms it will maybe not look lite the segmented control.

To make the control usefull I need to be able to bind items to it, bind to selected index, have an event that is thrown when selected index is changed and be able to change the color.

The first I will do is to create a class in the shared project that inherits from View.

If the properties will be bindable you have to create a BindableProperty as shown in the code below.

To set the choises (items) of the control we’re creating a List of strings.

public static readonly BindableProperty ItemsProperty =
			BindableProperty.Create<FilterControl, List<string>>
		(p => p.Items, new List<string>());
 
public List<string> Items 
{
	get 
        {
		return GetValue (ItemsProperty) as List<string>;
	}
	set 
        { 
		SetValue (ItemsProperty, value);
	}
}

When the control is defined next step is to create a renderer for iOS. The renderer will inherit from ViewRenderer.

public class FilterControlRenderer : ViewRenderer<FilterControl, UISegmentedControl>

In the override of the OnElementChanged we will create the native control, UISegmentedControl. I will put the code to map the list of choises to the segment control in a separate private method so I also can use it if the list of choices is changed. Then I will call it from the override of the OnElementPropertyChanged method.

You need to listen to ValueChanged of the UISegmentedControl so you can write the value back to the Xamarin.Forms control. In the event for selection changed I want both the old and new value, there for will I dont set selected index from the renderer. Instead I call a method in the control that is setting SelectedIndex and throwing the selection changed event.

protected override void OnElementChanged (ElementChangedEventArgs<FilterControl> e)
{
	base.OnElementChanged (e);
 
	var segmentControl = new UISegmentedControl ();
        SetNativeControl (segmentControl);
 
	UpdateSegments ();
 
	segmentControl.SelectedSegment = Element.SelectedIndex;
	segmentControl.SizeToFit ();
 
	segmentControl.ValueChanged += (object sender, EventArgs args) => 
	{
		if(segmentControl.SelectedSegment != Element.SelectedIndex)
		{
		     Element.OnSelectedIndexChanged((int)segmentControl.SelectedSegment);
		}
	};
}
 
private void UpdateSegments()
{
	Control.RemoveAllSegments ();
 
	for (int i = 0; i < Element.Items.Count; i++) 
	{
		Control.InsertSegment (Element.Items [i],i,true);
	}
}
public void OnSelectedIndexChanged(int newValue)
{
        var args = new IndexChangedEventArgs () {
		NewValue = newValue,
		OldValue = SelectedIndex
	};
 
	SelectedIndex = newValue;
 
	if (SelectedIndexChanged != null) 
	{				
		SelectedIndexChanged (this, args);
	}
}

Of course we also need to update the native control if the value for selected index is changed. That code will be placed in the OnElementPropertyChanged method.

protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
        base.OnElementPropertyChanged (sender, e);
 
	if (e.PropertyName == FilterControl.SelectedIndexProperty.PropertyName) 
	{
		if (Control.SelectedSegment != Element.SelectedIndex) 
		{
		         Control.SelectedSegment = Element.SelectedIndex;
		}
	}

The complete code can be found on GitHub, https://github.com/dhindrik/XamarinFormsSamples/tree/master/SegmentedControl

If you want the control to be in the NavigationBar on iOS read this blog post.

Xamarin.Forms: Add content to TitleView in your iOS app

If you’re building an iOS app you maybe want to add content to the NavigationBar. This blog post will show you how to build a generic solution so you don’t have to write a custom renderer for each view that you want NavigationBar content for.

First of all I creating a new class that inherits from ContentPage and adding a property of type View. I use to name the property TitleView, because that’s the name in iOS.

public class ExtendedContentPage : Xamarin.Forms.ContentPage
{
    public View TitleView { get; set; }
}

Now If your views/pages inherits from your new class you can add content to TitleView.

<local:ExtendedContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TitleViewSample"
             x:Class="TitleViewSample.MainView">
  <local:ExtendedContentPage.TitleView>
    <Button x:Name="TestButton" Text="Test" BackgroundColor="Green" />
  </local:ExtendedContentPage.TitleView>
</local:ExtendedContentPage>

To get it work you also have to write a custom page renderer for iOS. Override the WillMoveToParentViewController method in the renderer that will inherit PageRenderer and add the code below.

 base.WillMoveToParentViewController(parent);
 
 var page = (ExtendedContentPage)Element;
 
 var renderer = RendererFactory.GetRenderer(page.TitleView);
 var view = renderer.NativeView;
 view.SizeToFit();
 
 parent.NavigationItem.TitleView = view.Subviews[0];

It is important that you adding the first subview of the native view, otherwise it will be just blank.

The complete code can be found on GitHub, https://github.com/dhindrik/XamarinFormsSamples/tree/master/TitleView

Building a ScreenshotManager to capture the screen with code

This blog post will show you how to build a screenshot manager to use from shared code when building apps with Xamarin for Windows Phone, Android and iOS.

First of all we need to create an interface in the shared code library. In this example there will be one method in the screenshot manager. This method will capture the screen and return a byte array that you for example can save to a server.

 public interface IScreenshotManager
 {
        Task<byte[]> CaptureAsync();
 }

All platforms that we will target capture the screen in different ways. Therefor will each platform have a own implementation of the interface. If you register the interface with a platform specific implementation for each platform you can call the ScreenshotManager from shared code.

Windows Phone
For Windows Phone you need to render the root frame into a WritableBitmap.

public class ScreenshotManager : IScreenshotManager
    {
        public async Task<byte[]> CaptureAsync()
        {
            var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
 
            var screenImage = new WriteableBitmap((int)rootFrame.ActualWidth, (int)rootFrame.ActualHeight);
            screenImage.Render(rootFrame, new MatrixTransform());
            screenImage.Invalidate();
 
            using (var stream = new MemoryStream())
            {
                screenImage.SaveJpeg(stream, screenImage.PixelWidth, screenImage.PixelHeight, 0, 100);
                var bytes = stream.ToArray();
                return bytes;
            }
        }
    }

iOS
For iOS you need the view from the RootViewController to create a screenshot from. This code will work for iOS7 and above.

public class ScreenshotManager : IScreenshotManager
    {
        public async System.Threading.Tasks.Task<byte[]> CaptureAsync()
        {
            var view = UIApplication.SharedApplication.KeyWindow.RootViewController.View;
 
            UIGraphics.BeginImageContext(view.Frame.Size);
            view.DrawViewHierarchy(view.Frame, true);
            var image = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();
 
            using(var imageData = image.AsPNG())
            {
                var bytes = new byte[imageData.Length];
                System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, bytes, 0, Convert.ToInt32(imageData.Length));
                return bytes;
            }
 
        }
    }

Android
To create a screenshot in Android you need to have access to a activity. The easiest way to access a activity is to create a static method on the ScreenshotManager that you setting before using the ScreenshotManager.

public class ScreenshotManager : IScreenshotManager
    {
        public static Activity Activity { get; set; }
 
        public async System.Threading.Tasks.Task<byte[]> CaptureAsync()
        {
            if(Activity == null)
            {
                throw new Exception("You have to set ScreenshotManager.Activity in your Android project");
            }
 
            var view = Activity.Window.DecorView;
            view.DrawingCacheEnabled = true;
 
            Bitmap bitmap = view.GetDrawingCache(true);
 
            byte[] bitmapData;
 
            using (var stream = new MemoryStream())
            {
                bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
                bitmapData = stream.ToArray();
            }
 
            return bitmapData;
        }
    }

Using Context Actions in Xamarin.Forms ListView

One of the news in Xamarin.Forms 1.3 is what Xamarin call context actions. With context actions you can make a ListView much more richer. What you can do is to add a menu to every row in the ListView. On Windows Phone and Android is the menu showing when you’re long pressing on a item, on iOS you will swipe left on the item to show the menu. As you can see on the screenshots below the menu looks different on each platform. On Windows Phone the menu will pop up, on iOS it will be be on the row and on Android at the top of the screen.

contextactions contextactions_android contextactions_ios

To use context action add them to the ViewCell in the ItemTemplate as shown in the code below.

 <ViewCell.ContextActions>
       <MenuItem Text="Share" />
       <MenuItem Text="Buy" Command="{Binding AddToBasket}" />
</ViewCell.ContextActions>

MenuItem has four properties that is good to know:
Text: What’s shown to the user
Clicked: Adds a event listener to the menu item.
Command: Bind a command to the menu item.
IsDestructive: Will make the menu item red on iOS if it’s set to true.

 <ListView ItemsSource="{Binding Products}" VerticalOptions="Start" RowHeight="40">
 
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.ContextActions>
              <MenuItem Text="Share" />
              <MenuItem Text="Buy" Command="{Binding AddToBasket}" />
            </ViewCell.ContextActions>
 
            <ContentView Padding="0,10">
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="2*" />
                  <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
 
              <Label Text="{Binding Product.Name}" TextColor="Black" />
              <Label Grid.Column="1" HorizontalOptions="End" Text="{Binding Product.Price, StringFormat='{0:0.00} kr'}" TextColor="Red" />
 
              </Grid>
            </ContentView>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

Grouping a ListView – Xamarin.Forms

In many cases when you want a list of items you want to group them in the list. To use groups in a ListView with Xamarin.Forms is very easy.

Below are screenshots from Android, iOS and Windows Phone where there is no HeaderTemplate used.
android_groups ios_groups wp_groups

First step is to create a group class that inherits from ObservableCollection and create two properties, one for title and one for short title.

public class ListViewModel
{
     ObservableCollection<MyListViewGroup> Groups {get; set;}
}
 
public class MyListViewGroup : ObservableCollection<MyListViewItem>
{
     public string Title {get; set;}
     public string ShortTitle {get; set;}
}
 
public class MyListViewItem
{
     public string Name {get; set;}
}

IsGroupingEnabled is the keyword to enable grouping for the ListView, if it’s value is true the ListView will be grouped.

GroupTitle is the group title.

GroupShortTitle is the value that will be shown when you tap a group title in Windows Phone and the value at the left side on iOS. Android will not use GroupShortTitle. It will be used to jump a specific group.

To style the header use the GroupHeaderTemplate property.

 <ListView Grid.Row="1" ItemsSource="{Binding Groups}" 
           GroupShortNameBinding="{Binding ShortTitle}" IsGroupingEnabled="true" 
           GroupDisplayBinding="{ Binding Title }">
            <ListView.GroupHeaderTemplate>
              <DataTemplate>
                <ViewCell>
                  <ViewCell.View>
                    <Label Text="{Binding Title}" />
                  </ViewCell.View>
                </ViewCell>
              </DataTemplate>
            </ListView.GroupHeaderTemplate>
            <ListView.ItemTemplate>
              <DataTemplate>
                   <TextCell Text="{Binding Name}" />
              </DataTemplate>
            </ListView.ItemTemplate>
</ListView>

Monitor an app with Xamarin Insights

I Think it’s really important to monitor apps. Of course the most important part is to log errors in the app. But I also like to track how my users uses my apps. For the lastest app I have built I have used a monitoring tool from Xamarin called Insights, http://xamarin.com/insights.

While I alwas have crossplatform and testability in mind when I buildning apps I first create a logger interface.

public interface ILogger
{
     Task InitializeAsync();
 
    //Log exceptions
     void LogException(Exception ex);
 
     //Log information about events, for example view navigation
     Task TrackAsync(string identifier, Dictionary<string, string> details = null);
 
     //Log information about a user
     Task Identify(string userId, Dictionary<string, string> details = null);
}

While Xamarin Insights is compatible with Portable Class Library I writing the implementation in a project that I can share between platforms.

public class InsightsLogger : ILogger
{
     public virtual Task InitializeAsync()
     {
     }
 
     public void LogException(Exception ex)
     {
           Insights.Report(ex, ReportSeverity.Error);
     }
 
     public Task TrackAsync(string identifier, Dictionary<string, string> details = null)
     {
           Insights.Track(identifier, details);
     }
 
     public Task Identify(string userId, Dictionary<string, string> details = null)
     {
          Insights.Identify(userId, details);
     }
}

The InitializeAsync method is virtual so it can be overridden, when using Xamarin Insights each platform has to have the Initialize code. Because of that I also need to create a logger class for each platform.

While I don’t want errors from development together with production data I use to create two apps in Insights, one for development and one for production. I using conditional compile for to initialize with the right app key.

 public class WinPhoneInsightsLogger : Logging.InsightsLogger
    {
        public override async Task Initialize()
        {
#if DEBUG
            Insights.Initialize("key for debug use");
#else
            Insights.Initialize("key for production use");
#endif
        }
    }

if you want to read more about Xamarin Insights you can do it here, http://xamarin.com/insights

Crossplatform and storage strategies

Many applications need to store data related to the application. If you’re building applications for multiple platforms the APIs for storage is different.

Following five storage types is the most common ones:

Local storage
Storage to store application data locally on the device.

Remote storage
Storage to store application data in the cloud, for example OneDrive or iCloud. Data that is saved in the cloud could be accessible from different devices.

Cache storage
Storage to use when caching data. Platforms that have a separate storage for cache data will not contain cache storage in the backup, WinRT for an example. Cached data is not necessary to have in a backup, it will be cached again after restore of the backup.

Settings storage
Storage to store application settings locally on the device.

Remote settings storage
Storage to store application settings in the cloud, for example OneDrive or iCloud. Settings will be synced for all devices you have installed the application on.

You can handle storage in different ways, one strategy is to create one interface for each of the storage types above, for example ILocalStorage and IRemoteStorage. Every interface will have an implementation for each platform. With help of an IoC-container (Inversion of Control) we can use the interface to call platform specific code from shared code.

public interface ILocalStorage
{
     Task AddAsync(string key, object value);
     Task<T> GetAsync(string key, object value);
     Task<bool> ContainsAsync(string key);
     Task RemoveAsync(string key);
}

One other strategy is to create one storage interface, IStorage and have a method with storage type as an argument. As with the first strategy each platform will have a platform specific implementation that can be used from shared code with help of IoC.

public enum StorageTypes
{
    Local,
    Remote,
    Cache,
    Settings,
    RemoteSettings
}
 
public interface IStorage
{
     Task AddAsync(string key, object value, StorageTypes storageType);
     Task<T> GetAsync(string key, object value, StorageTypes storageType);
     Task<bool> ContainsAsync(string key, StorageTypes storageType);
     Task RemoveAsync(string key, StorageTypes storageType);
}
 
public class Storage : IStorage
{
     public async Task AddAsync(string key, object value, StorageTypes storageType)
     {
          switch(storageType)
          {
                 case StorageTypes.Local:
                      //code for local storage
                      break;  
                 case StorageTypes.Remote:
                      //code for remote storage
                      break;  
                 case StorageTypes.Cache:
                      //code for cache storage
                      break;  
                 case StorageTypes.Settings:
                      //code for settings storage
                      break;  
                 case StorageTypes.RemoteSettings:
                      //code for remote settings storage
                      break;  
          }     
     }

I prefer the first strategy beacause I like small classes with one role, the maintainability will be much higher and you can make changes to one implementation without the risk of breaking other functionality than that one you want to change.

As an example, one platform maybe don’t have CacheStorage, then the LocalStorage and CacheStorage will be pretty much the same. But if that platform will get CacheStorage in the future you can change the implementation of ICacheStorage without touching the working code for LocalStorage.

Extend Label in Xamarin.Forms with a font color property

The label control in Xamarin.Forms does not have a FontColor property. But the control is easy to extend.

First create a new class that inherits from Label.
Create a FontColor property of type string. The value of the FontColor will in this example be an RGBA string.

public class CustomLabel : Label
    {
 
         public static readonly BindableProperty FontColorProperty = 
             BindableProperty.Create<CustomLabel, string>( 
                 p => p.FontColor, ""); 
 
 
         public string FontColor
         { 
             get 
             { 
                 return (string)GetValue(FontColorProperty); 
             } 
             set 
             { 
                 SetValue(FontColorProperty, value); 
             } 
         } 
 
    }

Next step is to write a custom renderer for each platform.

iOS

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyApp.iOS.Renderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
 
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "FontColor")
            {
                var view = (CustomLabel)Element;
 
                var values = view.FontColor.Split(',');
 
                Control.TextColor = UIColor.FromRGBA(int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]), int.Parse(values[3]));
            }
        }
    }
}

Android

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyApp.Android.Renderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
 
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "FontColor")
            {
                var view = (CustomLabel)Element;
 
                var values = view.FontColor.Split(',');
 
                var color = Color.Argb(int.Parse(values[3]),int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]));
 
                Control.SetTextColor(color);            
            }
        }
    }
}

Windows Phone

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyApp.WinPhone.Renderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
 
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "FontColor")
            {
                var view = (CustomLabel)Element;
 
                var values = view.FontColor.Split(',');
                Control.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromArgb(byte.Parse(values[0]), byte.Parse(values[1]), byte.Parse(values[2]), byte.Parse(values[3])));
            }
        }
    }
}

To use the custom label in XAML you need to declare the namespace.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="MyApp.Views.MyView"
            xmlns:controls="clr-namespace:MyApp.CustomControls;assembly=MyApp">

Then you can use the control i XAML like this:

<controls:CustomLabel FontColor="255,255,255,255" Text="My custom label" />

Xamarin.Forms: Change background color on iOS ListView

The ListView control in Xamarin.Forms has a background color property. But iOS has a default color on each cell, because of that it will not work to set a color with that property. One solution is to use a custom renderer for the ListView on iOS.

A custom renderer can be created for the ListView control, but I prefer to create a new control that inherit from ListView. Then I can use the ListView as standard as I want and I can use my customized ListView if I want.

The first step i to create a new control that inherits from ListView.

public class MyListView : ListView
{
}

Next step is to create the CustomRenderer for iOS. To do that create a new class in your iOS project (If you don’t create a custom ListView for the other platforms, the standard renderer will be used). Your new class will inherit from ListViewRenderer. In the custom renderer you will override the OnElementPropertyChanged method.
In this method you can do the changes you want to do to the ListView. This code will run every time a property is changed on the ListView. In this case we only need to run our code when it’s the ItemsSource property that is changed.

public class MyListViewRenderer : ListViewRenderer
{
    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "ItemsSource")
            {
                var control = (UITableView)Control;
 
                foreach (var cell in control.VisibleCells)
                {
                    cell.BackgroundColor = UIColor.FromRGB(255, 0, 0);
                }
            }
 
        }
}

To use the custom renderer we need to add an assembly attribute outside the class and the namespace.

[assembly: ExportRenderer(typeof(MyListView), typeof(MyListViewRenderer))]
namespace MyApp.iOS
{

To use your new control i your XAML you need to include the namespace for it.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:myControls="clr-namespace:MyApp.Controls;assembly=MyApp"

Then you can use it with the alias you assign to it in the namespace declaration.

<myControls:MyListView>
   <!-- ListView content -->
</myControl:MyListView>

Building a tabbed app using Xamarin.Forms

Xamarin.Forms is one of the biggest news with Xamarin 3. With Xamarin.Forms you can build UI for 3 platforms (Windows Phone, iOS and Android) with one shared codebase. What is unique for Xamarin.Forms is that the UI code you are writing with Xamarin.Forms will render native UI controls. That means that the UI will look like a Windows Phone app when running the code on a Windows Phone and it will look like a iPhone app when running the code on an iPhone and the same on Android.

Create a Xamarin.Forms project in Visual Studio
This post will show you the basics when building an app with Xamarin.Forms in Visual Studio 2013. You can also build apps using Xamarin.Forms with Xamarin Studio but for the Windows Phone project you need to use Visual Studio.

To create an app with Xamarin.Forms open the new project dialog. Xamarin.Forms project templates is located under “Mobile Apps”. There are three types of project you can create, a blank app with the code in a project of type portable class library (the project will be referenced in each client project), a blank app with shared code (you have to link the each file to each client project) and a class library of type portable class library.

In this tutorial I will use the first choice because I want Visual Studio to create the client projects (projects for Windows Phone, iOS and Android) and I think it’s easier to reference an assembly than linking files.

Create dialog

Now Visual Studio has created four projects, the client projects and a project for the shared UI code.

In the shared project I add a new item based on the template called “Forms Xaml Page”. Then a XAML-file and a code behind file is created.

Many of the tutorials I have read writes the most of the code in the code behind file, but I want to use XAML as much as possible. One disadvantage to use Visual Studio is that there is not intellisense for the XAML-code. If you miss it to much you can use Xamarin Studio instead.

Create an app with tabs

The app in this tutorial will be a app with two tabs/views and for that we will use a tabbed page. This post will just use standard styles. But you can both style the app for all platforms or you can do platform specific styling.

In the view we just created ad the code below. This will be a container for the views in the app.

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="FormsDemo.FirstView"
            Title="News">
 
</TabbedPage>

You also need to go to the code behind file and make the class inherit from “TabbedPage”.

Next step is to create the content views, this app will have one for news and one for settings, so I add two new forms xaml pages to the shared project. Before I starting to create each view I will add them to the tabbed page. This is done from the code behind file of our “container”.

public partial class FirstView : TabbedPage
    {
        public FirstView()
        {
            InitializeComponent();
 
            Children.Add(new NewsView());
            Children.Add(new SettingsView());
 
        }
    }

The title for the tabs will be the title we set as Title property on ContentPage for each view.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="FormsDemo.NewsView" Title="News">

Add a list to the app
My first tab will be a list with news. For that I using the ListView control that is included in Xamarin.Forms.

<ListView x:Name="News" ItemsSource="{Binding News}" RowHeight="80" BackgroundColor="Transparent">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <ViewCell.View>
            <StackLayout Orientation="Vertical" Spacing="0" Padding="10">
              <Label Font="Bold,20" Text="{Binding Header}" />
              <Label Font="16" Text="{Binding Text}" />
            </StackLayout>
          </ViewCell.View>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>

And the code behind will look like this:

public partial class NewsView
    {
        public NewsView()
        {
            InitializeComponent();
 
            BindingContext = new NewsViewModel();
        }
    }
 
    public class NewsViewModel
    {
        public NewsViewModel()
        {
            News = new List<NewsItem>()
            {
                new NewsItem()
                {
                    Header = "Header 1",
                    Text = "Text 1"
                },
                new NewsItem()
                {
                    Header = "Header 2",
                    Text = "Text 2"
                }
            };
        }
 
        public List<NewsItem> News { get; set; }
    }
 
    public class NewsItem
    {
        public string Header { get; set; }
        public string Text { get; set; }
    }

iPhone

Windows Phone

Android

On the settings page I using the Switch control to turn news sources on or off.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="FormsDemo.SettingsView">
  <StackLayout Orientation="Vertical" Padding="10">
	  <Label Font="Bold,20" Text="News sources" />
    <StackLayout Orientation="Horizontal">
      <Label Text="Xamarin" VerticalOptions="Center" />
      <Switch VerticalOptions="Center" />
    </StackLayout>
    <StackLayout Orientation="Horizontal">
      <Label Text="Microsoft" VerticalOptions="Center" />
      <Switch VerticalOptions="Center" />
    </StackLayout>
  </StackLayout>
</ContentPage>

Windows Phone

Android

iPhone


That was the basics to build an tabbed app with Xamarin.Forms. Of course you can do much more than this with Xamarin.Forms.

TechDays 2014

Den 19-20 november (17-20 november med pre-conf inkluderat) anordnas utvecklarkonferensen TechDays av Microsoft. Jag och min Sogeti- och IO2GameLabs kollega Johan Karlsson har fått äran att vara med på den. Vi kommer att prata om det vi brinner mest för nämligen cross platform utveckling för mobila enheter.

På pre-conf (den 17 november) kommer vi tillsammans med Peter Bryntesson (Microsoft), Johan Lindfors (Coderox) och Anderas Hammar (Jayway) att hålla en heldag om hur man bygger appar för Windows (Windows Store och Windows Phone) och för iOS och Android med Xamarin. Läs mer här.

Under själva huvudkonferensen kommer jag och Johan att ägna ca en timme till att berätta hur vi har arbetat med vårt spel WordRoom för att göra det cross platform med Xamarin och Microsoft Azure. Läs mer här.

Tycker ni att detta låter intressant tycker jag ni ska komma till TechDays på Kistamässan, självklart kommer det bjudas på massa andra intressanta föreläsningar också. Se hela programmet här.

Windows Azure Mobile Services in Portable Class Library

In my current project, a multiplayer game for mobile devices I only using Windows Azure Mobile Services as backend. The game will be available for multiple platforms and I will use Xamarin for iOS and android.

When using Xamarin I can reuse a lot of code if I using PCL (Portal Class Library) that i shipped with Visual Studio. When creating a new PCL-project you can choose which taget platforms the project will build for, in my case Windows Phone, Windows Store, Xamarin iOS and Xamarin Android.

In order to reuse so much code as possible I want to have the communication with my backend in PCL. When using Windows Azure Mobile Services I can have all communication there except for the code for authentication. But then I put an interface i PCL and each platform will have a specific implementation of the interface.

But where to find the Mobile Services assemblies for PCL? I installed Mobile Services via NUGET to my Windows Phone project (Windows Phone is my first platform). But Mobile Services was not just installed to my Windows Phone project, I also got the assemblies for PCL (and other platforms) i my packages folder. It enabled me to add the assemblies manually to the PCL-project.

Modern UI icons

If you searching for icons for your app or website, check out http://modernuiicons.com/. There are over 1000 icons designed for your app or website. It is a very good library when building modern UI apps for Windows Phone, Windows 8 or iOS7. But I have also used them for different websites. When I searching for icons I almost always finds an icon in Modern UI icons library.

When you download the library you will get a dark and a white version of the icon. But you also got them in the vector format, .design and .svg.

Size limit on app download when using 3G

iOS and Windows Phone has size limit on how big apps you can downloaded when you’re not connected to a Wi-Fi-network. Windows Phone has a limit on 20 Mb and iOS has 50 Mb.  Android has not that type of limit, but an APK on Google Play is limited to 50 Mb, but you can add extensions that are much bigger than so.

When are you downloading apps to your phone? It’s often when you sitting on the bus or waiting for something. Do you have a Wi-Fi-connection then? Often not.

I think it could be a good thing to think about when developing apps. If a user found your app and cannot download it, the chance that they choose to download another app instead is big. If you have big content in you app, you maybe can have it on a server and download it when the user starting the app.

Probably the user don’t need that content from start and you have some time to download it, if they navigate to a part that need the content, show a loading dialog that tells the user that content is under download.

Authentication with Azure Mobile Services

When developed the multiplayer part of WordRoom we discussed to use different authentication providers. But it was a lot of code to integrate each provider. And we wanted more than one. Instead we developed our own solution.

But just ask yourself, do you want to create an account everywhere with different username and passwords. I don’t. When we discovered Azure Mobile Services it was an obvious choice. Mobile Service gives you authentication with Microsoft-, Google-, Facebook and Twitter account and it’s for free. You only need to connect it to a database server. But we already had a database server in Azure. So i next version of WordRoom, you can authenticate with your Microsoft-, Google-, Facebook- or Twitter account.

With just a few rows of code you can authenticate the user with one of the authentication providers.
That Mobile Service is for five different platforms is a huge strength. You can use it for Windows Store applications, Windows Phone, Android, iOS and HTML5/JavaScript. If you use Xamarin Studio for developing your Android and iOS apps, there is a third part library.

In a Windows Store application you just add the SDK, some rows in App.xaml.cs and one row where you want to authenticate the user.

user = await App.MobileService
                .LoginAsync(MobileServiceAuthenticationProvider.Facebook);

Read more about Mobile Services

 

Developing apps with mono

WordRoom started as a Windows Phone project, the third client we started to develop and the first one we released was for Windows 8. We developed the windows 8 relative fast because we could reuse a lot of the code from the Windows Phone project in that we used portal library for the core logic.

As I mentioned above, Windows 8 was the third client we started to develop. The second was for android devices. I started to build the android client with java and eclipse. Step one was to translate all core logic from C# to java, a lot of work but I developed an almost finished client for WordRoom. But in the end of 2012 when we should start to develop the client for iOS we decided to use and mono touch and mono for android from Xamarin so that we could use the same assemblies for the core logic that we did when developing for the Windows platforms. We also share data contract assemblies between the backend and the clients. So now we running the same code in at backend in Windows Azure, on Windows 8, Windows Phone, Android and iOS.

The decision to start using mono is one of the best decision we have taken. We saving a lot of time and we get an app that is much easier to maintain.

Next app I will develop I will think about that that the code will be shared between different platforms earlier in the process. Because if you have a structure in your project with GUI and business/game logic split up and using interfaces for platform specific features, for example local storage you can reuse much more code and save a lot of time.