I have created a custom map and all works fine. Except that I am not able show device location on the map. The controls for zoom and current location do not appear either. I tried getting the location using Plugin.Geocoder but The map doesn't want to center to that location.
MainPage.xaml.cs
using Plugin.Geolocator;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
namespace CMap
{
public partial class MainPage : ContentPage
{
public Map StockistMap;
public MainPage()
{
InitializeComponent();
Initialize();
StockistMap = new Map()
{
IsShowingUser = true,
HeightRequest = 800,
WidthRequest = 960,
IsVisible = true,
MapType = MapType.Street,
VerticalOptions = LayoutOptions.FillAndExpand
};
var position1 = new Position(36.8961, 10.1865);
var position2 = new Position(36.891, 10.181);
var position3 = new Position(36.892, 10.182);
var position4 = new Position(36.893, 10.183);
var position5 = new Position(36.891, 10.185);
var position6 = new Position(36.892, 10.187);
var customPin1 = new CustomPin
{
Pin = new Pin
{
Type = PinType.Place,
Position = position1,
Label = "IntilaQ",
Address = "Technopark Elgazala, Tunisia"
},
URL = "www.intilaq.tn",
};
var customPin2 = new CustomPin
{
Pin = new Pin
{
Type = PinType.SearchResult,
Position = position2,
Label = "Telnet R&D",
Address = "Technopark Elgazala, Tunisia"
},
URL = "www.groupe-telnet.com"
};
var customPin3 = new CustomPin
{
Pin = new Pin
{
Type = PinType.SearchResult,
Position = position3,
Label = "Kromberg&Schubert",
Address = "Technopark Elgazala, Tunisia"
},
URL = "www.kromberg-schubert.com"
};
var customPin4 = new CustomPin
{
Pin = new Pin
{
Type = PinType.SearchResult,
Position = position4,
Label = "Via Mobile",
Address = "Technopark Elgazala, Tunisia"
},
URL = "www.kromberg-schubert.com"
};
var customPin5 = new CustomPin
{
Pin = new Pin
{
Type = PinType.SearchResult,
Position = position5,
Label = "Via Mobile",
Address = "Technopark Elgazala, Tunisia"
},
URL = "www.kromberg-schubert.com"
};
var customPin6 = new CustomPin
{
Pin = new Pin
{
Type = PinType.SearchResult,
Position = position6,
Label = "Via Mobile",
Address = "Technopark Elgazala, Tunisia"
},
URL = "www.kromberg-schubert.com"
};
StockistMap.Pins.Add
(
customPin1.Pin
);
MapContainer.Children.Add(StockistMap);
}
private async void Initialize()
{
await RetrieveLocation();
}
private async Task RetrieveLocation()
{
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
var position = await locator.GetPositionAsync(TimeSpan.FromSeconds(10));
StockistMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromKilometers(10)));
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
}
}
}
CustomMap.cs
using System.Collections.Generic;
using Xamarin.Forms.Maps;
namespace CMap
{
public class CustomMap : Map
{
public List<CustomPin> CustomPins { get; set; }
}
}
CustomPin.cs
using System;
using Xamarin.Forms.Maps;
namespace CMap
{
public class CustomPin
{
public Pin Pin { get; set; }
public String URL { get; set; }
}
}
CustomMapRenderer.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using CMap;
using CMap.Droid.Platform;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CMap.Droid.Platform
{
public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter, IOnMapReadyCallback
{
private GoogleMap _map;
private List<CustomPin> _customPins;
private bool _isDrawn;
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
_map.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
_customPins = formsMap.CustomPins;
((MapView)Control).GetMapAsync(this);
}
}
public void OnMapReady(GoogleMap googleMap)
{
_map = googleMap;
_map.InfoWindowClick += OnInfoWindowClick;
_map.SetInfoWindowAdapter(this);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("VisibleRegion") && !_isDrawn)
{
_map.Clear();
foreach (var pin in _customPins)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude));
marker.SetTitle(pin.Pin.Label);
marker.SetSnippet(pin.Pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
_map.AddMarker(marker);
}
_isDrawn = true;
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (changed)
{
_isDrawn = false;
}
}
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
var customPin = GetCustomPin(e.Marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
if (!string.IsNullOrWhiteSpace(customPin.URL))
{
var url = Android.Net.Uri.Parse(customPin.URL);
var intent = new Intent(Intent.ActionView, url);
intent.AddFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
}
}
public Android.Views.View GetInfoContents(Marker marker)
{
var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater;
if (inflater != null)
{
Android.Views.View view;
var customPin = GetCustomPin(marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);
if (infoTitle != null)
{
infoTitle.Text = marker.Title;
}
if (infoSubtitle != null)
{
infoSubtitle.Text = marker.Snippet;
}
return view;
}
return null;
}
public Android.Views.View GetInfoWindow(Marker marker)
{
return null;
}
CustomPin GetCustomPin(Marker annotation)
{
var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
foreach (var pin in _customPins)
{
if (pin.Pin.Position == position)
{
return pin;
}
}
return null;
}
}
}