en
de

Xamarin.Forms: A new perspective of mobile app development

13 April 2015
| |
Reading time: 5 minutes

The Xamarin platform is very popular at Zühlke as a way to develop cross-platform mobile apps. I had heard a lot about it and after a few years of native app development, I had the opportunity to use Xamarin.Forms in a customer project. After a short period of time I just can say: I’m impressed.

Xamarin offers the possibility to develop cross-platform apps for mobile devices (not only, but that’s definitely the main focus). The big problem with cross-platform apps is that you need to do all the work multiple times. In most cases, customers want at least iOS and Android support, so if one would like to have the same app on those two platforms, the amount of work for the developers would be nearly twice as high. Not only for the development, but also for maintenance.

There are a lot of approaches to offer a solution to that problem, and Xamarin is one of them. The idea is to share code wherever possible to reduce the amount of work on different platforms. When using Xamarin, everything is done using C#. You will have a shared codebase containing the application logic, which is exactly the same across all platforms. The UI is developed multiple times and is platform-specific. In my opinion, that’s a good thing. Native UI is still the best choice when it comes to responsiveness and high quality look and feel.

Xamarin.Forms

But the folks at Xamarin took that idea a step further. Even when it comes to UI, there are common principles and components that iOS, Android and Windows Phone share. Most of the time those components just have different names, but when it comes to the absolute basic functionality they are exactly the same. All platforms have elements like views, textboxes, labels or buttons. Many basic navigation concepts are also pretty much the same thing. So there is an intersection of UI principles and components available across all platforms. With Xamarin.Forms this intersection is represented as an abstraction layer above the platform specific UI, enabling developers to write the application logic and the UI once and to produce native apps for each individual platform.

Sounds great, but how does it perform in a real world scenario? First of all, Xamarin.Forms isn’t the solution to every problem. As far as my experience goes up until today, it’s perfect if you don’t need a lot of custom UI or platform-specific services. Some customization is possible, but it’s quite limited. If standard UI without customization is fine for you, then Xamarin.Forms can really speed up the development and saves you a lot of work. There are a few quite good Projects extending Xamarin.Forms, like Xamarin.Forms Labs. It provides phone or geolocation services, but also more UI components than Forms does. Definitely worth a look.

Xamarin.Forms.Maps

So much about Xamarin and Forms in general. I was wondering what would happen if there would be a scenario where all the out-of-the-box magic of Forms would not give me a satisfying solution. I had that exact experience with Xamarin.Forms.Maps.

Xamarin.Forms.Maps is not a part of Xamarin.Forms but comes as a separate NuGet package. It offers the possibility to embed a map component which represents the intersection of an Apple, Google or Bing Maps component. You can access all the basic functionality like adding pins or navigating to certain points around the world.

Unfortunately, neither the graphical representation of the location (the pin itself) nor the little information callout containing the address string is meant to be customized, at least with the methods provided by Forms.Maps. Also, there is a bug that a tap on the pin is only recognized on Android, not on iOS. I know that some people on Stack Overflow and on the Xamarin forums had the same problem, so I want to present my solution in a more tutorial-like style. I will not go into all the implementation details and just point out some key steps. For the whole solution just take a look on my FormsMapZ example on GitHub.

Map before customization

Standard callout (iOS) and Info Window (Android) with Forms.Maps

Custom Renderers

Fortunately, Xamarin.Forms offers a solution for such situations. When a Xamarin.Forms component lacks functionality that is absolutely necessary for you, you can extend the component by providing a Custom Renderer. I think the term Renderer is a bit misleading, because it suggests that you take over the drawing or graphical rendering of a component. But a Custom Renderer is just an entry point into the platform-specific world. In my example, I needed a custom Callout (iOS speak) and a custom Info Window (Android speak). That’s the little popup with the address in it which appears after selecting a pin on the map.

So I implemented two Custom Renderers for iOS and Android. By providing my own renderer, I can access the platform-specific map component, which is a GoogleMap on Android and a MKMapView on iOS. The method you need to implement is OnElementPropertyChanged, which will provide the instance used in your shared code. On iOS, we need to implement our own MKMapDelegate to override the methods responsible for displaying the pin and the callout view, which is GetViewForAnnotation.

protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
    base.OnElementChanged(e);
    if (Map != null)
    {
        //Entry point into the iOS world
        Map.Delegate = new MyMapViewDelegate((ExtendedMap)e.NewElement);
    }
}
public override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
    //The users location is handled by the os
    if (mapView.UserLocation.Location != null && annotation.Coordinate.Equals(mapView.UserLocation.Location.Coordinate))
    {
        return null;
    }

    const string defaultPinIdentifier = "defaultPin";
    MKPinAnnotationView pinAnnotationView = (MKPinAnnotationView)mapView.DequeueReusableAnnotation(defaultPinIdentifier);

    //This is where we can customize the pin (callout, image, ...)
    if (pinAnnotationView == null)
    {
        pinAnnotationView = new MKPinAnnotationView(annotation, defaultPinIdentifier)
        {
            CanShowCallout = true,
            Annotation = annotation,
        };

        UIButton rightButton = new UIButton(UIButtonType.DetailDisclosure);
        pinAnnotationView.RightCalloutAccessoryView = rightButton;
    }
    else
    {
        pinAnnotationView.Annotation = annotation;
    }
    return pinAnnotationView;
}

After that, the pin on the map component opens a customized view as its callout, displaying a button. By the way, the iOS pin selection bug was also solved with that Custom Renderer, using the Xamarin Messaging Center to notify other components about the selection of a pin. See my code on GitHub if you’re interested.

Map after customization

Callout (iOS) and Info Window (Android) after the development of a Custom Renderer

My Thoughts

Before I started with Xamarin.Forms, I developed a bit of native Android and a lot of native iOS. Xamarin.Forms gave me a whole new perspective. Even when it’s needed to extend Forms components with Custom Renderers, I never felt lost or had the impression that the technology was the wrong choice. The combination of Xamarin, Visual Studio, C# and the surrounding infrastructure is very impressive and speeds up many aspects of development. For the future, I will think twice before developing a native app, even if cross-platform is not a requirement.

Comments (0)

×

Sign up for our Updates

Sign up now for our updates.

This field is required
This field is required
This field is required

I'm interested in:

Select at least one category
You were signed up successfully.

Receive regular updates from our blog

Subscribe

Or would you like to discuss a potential project with us? Contact us »