Highlighting a Route on a Map
- PDF for offline use
- Sample Code:
- Related Articles:
- Related APIs:
Let us know how you feel about this
Translation Quality
0/250
last updated: 2017-08
This article explains how to add a polyline overlay to a map. A polyline overlay is a series of connected line segments that are typically used to show a route on a map, or form any shape that's required.
Overview
An overlay is a layered graphic on a map. Overlays support drawing graphical content that scales with the map as it is zoomed. The following screenshots show the result of adding a polyline overlay to a map:

When a Map control is rendered by a Xamarin.Forms application, in iOS the MapRenderer class is instantiated, which in turn instantiates a native MKMapView control. On the Android platform, the MapRenderer class instantiates a native MapView control. On the Universal Windows Platform (UWP), the MapRenderer class instantiates a native MapControl. The rendering process can be taken advantage of to implement platform-specific map customizations by creating a custom renderer for a Map on each platform. The process for doing this is as follows:
- Create a Xamarin.Forms custom map.
- Consume the custom map from Xamarin.Forms.
- Customize the map by creating a custom renderer for the map on each platform.
Xamarin.Forms.Maps must be initialized and configured before use. For more information, see Maps Control.
For information about customizing a map using a custom renderer, see Customizing a Map Pin.
Creating the Custom Map
Create a subclass of the Map class, that adds a RouteCoordinates property:
public class CustomMap : Map
{
public List<Position> RouteCoordinates { get; set; }
public CustomMap ()
{
RouteCoordinates = new List<Position> ();
}
}
The RouteCoordinates property will store a collection of coordinates that define the route to be highlighted.
Consuming the Custom Map
Consume the CustomMap control by declaring an instance of it in the XAML page instance:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MapOverlay;assembly=MapOverlay"
x:Class="MapOverlay.MapPage">
<ContentPage.Content>
<local:CustomMap x:Name="customMap" MapType="Street" WidthRequest="{x:Static local:App.ScreenWidth}" HeightRequest="{x:Static local:App.ScreenHeight}" />
</ContentPage.Content>
</ContentPage>
Alternatively, consume the CustomMap control by declaring an instance of it in the C# page instance:
public class MapPageCS : ContentPage
{
public MapPageCS ()
{
var customMap = new CustomMap {
MapType = MapType.Street,
WidthRequest = App.ScreenWidth,
HeightRequest = App.ScreenHeight
};
...
Content = customMap;
}
}
Initialize the CustomMap control as required:
public partial class MapPage : ContentPage
{
public MapPage ()
{
...
customMap.RouteCoordinates.Add (new Position (37.785559, -122.396728));
customMap.RouteCoordinates.Add (new Position (37.780624, -122.390541));
customMap.RouteCoordinates.Add (new Position (37.777113, -122.394983));
customMap.RouteCoordinates.Add (new Position (37.776831, -122.394627));
customMap.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (37.79752, -122.40183), Distance.FromMiles (1.0)));
}
}
This initialization specifies a series of latitude and longitude coordinates in order to define the route on the map to be highlighted. It then positions the map's view with the MoveToRegion method, which changes the position and zoom level of the map by creating a MapSpan from a Position and a Distance.
Customizing the Map
A custom renderer must now be added to each application project in order to add the polyline overlay to the map.
Creating the Custom Renderer on iOS
Create a subclass of the MapRenderer class and override its OnElementChanged method in order to add the polyline overlay:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.iOS
{
public class CustomMapRenderer : MapRenderer
{
MKPolylineRenderer polylineRenderer;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null) {
var nativeMap = Control as MKMapView;
if (nativeMap != null) {
nativeMap.RemoveOverlays(nativeMap.Overlays);
nativeMap.OverlayRenderer = null;
polylineRenderer = null;
}
}
if (e.NewElement != null) {
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
nativeMap.OverlayRenderer = GetOverlayRenderer;
CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[formsMap.RouteCoordinates.Count];
int index = 0;
foreach (var position in formsMap.RouteCoordinates)
{
coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
index++;
}
var routeOverlay = MKPolyline.FromCoordinates(coords);
nativeMap.AddOverlay(routeOverlay);
}
}
...
}
}
This method performs the following configuration, provided that the custom renderer is attached to a new Xamarin.Forms element:
- The
MKMapView.OverlayRendererproperty is set to a corresponding delegate. - The collection of latitude and longitude coordinates are retrieved from the
CustomMap.RouteCoordinatesproperty and stored as an array ofCLLocationCoordinate2Dinstances. - The polyline is created by calling the static
MKPolyline.FromCoordinatesmethod, which specifies the latitude and longitude of each point. - The polyline is added to the map by calling the
MKMapView.AddOverlaymethod.
Then, implement the GetOverlayRenderer method in order to customize the rendering of the overlay:
public class CustomMapRenderer : MapRenderer
{
MKPolylineRenderer polylineRenderer;
...
MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (polylineRenderer == null && !Equals(overlayWrapper, null)) {
var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
polylineRenderer = new MKPolylineRenderer(overlay as MKPolyline) {
FillColor = UIColor.Blue,
StrokeColor = UIColor.Red,
LineWidth = 3,
Alpha = 0.4f
};
}
return polylineRenderer;
}
}
Creating the Custom Renderer on Android
Create a subclass of the MapRenderer class and override its OnElementChanged and OnElementPropertyChanged methods in order to add the polyline overlay:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.Droid
{
public class CustomMapRenderer : MapRenderer
{
List<Position> routeCoordinates;
bool isDrawn;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null) {
// Unsubscribe
}
if (e.NewElement != null) {
var formsMap = (CustomMap)e.NewElement;
routeCoordinates = formsMap.RouteCoordinates;
Control.GetMapAsync(this);
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("VisibleRegion") && !isDrawn) {
var polylineOptions = new PolylineOptions();
polylineOptions.InvokeColor(0x66FF0000);
foreach (var position in routeCoordinates) {
polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
}
NativeMap.AddPolyline(polylineOptions);
isDrawn = true;
}
}
}
}
This method retrieves the collection of latitude and longitude coordinates from the CustomMap.RouteCoordinates property and stores them in a member variable. It then calls the MapView.GetMapAsync method, which gets the underlying GoogleMap that is tied to the view, provided that the custom renderer is attached to a new Xamarin.Forms element.
The polyline is created in the OnElementPropertyChanged method, which is called whenever any bindable properties in the custom map control change. The Xamarin.Forms.Maps.Map.VisibleRegion property contains coordinates for the currently visible region of the map, and will change prior to the map being displayed. When this occurs, a PolylineOptions object is instantiated that specifies the latitude and longitude of each point. The polyline is then added to the map by calling the NativeMap.AddPolyline method.
Creating the Custom Renderer on the Universal Windows Platform
Create a subclass of the MapRenderer class and override its OnElementChanged method in order to add the polyline overlay:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.UWP
{
public class CustomMapRenderer : MapRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MapControl;
var coordinates = new List<BasicGeoposition>();
foreach (var position in formsMap.RouteCoordinates)
{
coordinates.Add(new BasicGeoposition() { Latitude = position.Latitude, Longitude = position.Longitude });
}
var polyline = new MapPolyline();
polyline.StrokeColor = Windows.UI.Color.FromArgb(128, 255, 0, 0);
polyline.StrokeThickness = 5;
polyline.Path = new Geopath(coordinates);
nativeMap.MapElements.Add(polyline);
}
}
}
}
This method performs the following operations, provided that the custom renderer is attached to a new Xamarin.Forms element:
- The collection of latitude and longitude coordinates are retrieved from the
CustomMap.RouteCoordinatesproperty and converted into aListofBasicGeopositioncoordinates. - The polyline is created by instantiating a
MapPolylineobject. TheMapPolygonclass is used to display a line on the map by setting itsPathproperty to aGeopathobject that contains the line coordinates. - The polyline is rendered on the map by adding it to the
MapControl.MapElementscollection.
Summary
This article explained how to add a polyline overlay to a map in order to show a route on a map, or form any shape that's required.
Let us know how you feel about this
Translation Quality
0/250
Xamarin Workbook
If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.

