Cómo crear Mapas bindable en Xamarin.Forms (Parte 3)
![]()
Si estas desarrollando una plicación Xamarin.Forms y vas a utilizar mapas Xamarin.Forms.Maps, te permite visualizar un mapa dentro de una aplicación Xamarin.Forms. En este artículo veremos cómo mostrar varias ubicaciones, mostrar la ubicación actual y como generar una ruta. Puedes leer la primera parte en Cómo crear Mapas bindable en Xamarin.Forms (Parte 1) y Cómo crear Mapas bindable en Xamarin.Forms (Parte 2)
Para que las rutas funcionen se debe crear una clase en los proyectos iOS y Android para que se muestren las líneas de la ruta.
Androide
[assembly: ExportRenderer(typeof(CustomMap), typeof(logistico.Droid.CustomMapRender))]
namespace logistico.Droid
{
public class CustomMapRender: MapRenderer
{
List<Position> routeCoordinates;
public CustomMapRender(Context context) : base(context)
{
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(sender !=null){
var formsMap = (CustomMap)sender;
routeCoordinates = formsMap.RouteCoordinates;
Control.GetMapAsync(this);
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Map> e){
base.OnElementChanged(e);
if(e.OldElement!=null){
}
if(e.NewElement!=null){
var formsMap = (CustomMap)e.NewElement;
routeCoordinates = formsMap.RouteCoordinates;
Control.GetMapAsync(this);
}
}
protected override void OnMapReady(Android.Gms.Maps.GoogleMap map){
base.OnMapReady(map);
var polylineOptions = new PolylineOptions();
polylineOptions.InvokeColor(0x66FF0000);
foreach(var position in routeCoordinates){
polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
}
NativeMap.AddPolyline(polylineOptions);
}
}
}
iOS
[assembly: ExportRenderer(typeof(CustomMap), typeof(logistico.iOS.CustomMapRender))]
namespace logistico.iOS
{
public class CustomMapRender:MapRenderer
{
MKPolylineRenderer polylineRenderer;
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(sender!=null){
var formsMap = (CustomMap)sender;
var nativeMap = Control as MKMapView;
nativeMap.OverlayRenderer = GetOverlayRenderer;
if (formsMap.RouteCoordinates != null)
{
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);
}
}
}
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;
if(formsMap.RouteCoordinates!=null){
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);
}
}
}
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.DarkGray,
LineWidth = 3,
Alpha = 0.4f
};
}
return polylineRenderer;
}
}
}
Implementación en Xamarin.Forms
Para implementarlo en Xaml es de la siguiente manera
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:logistico"
xmlns:cntrl="clr-namespace:logistico.Controls"
x:Class="logistico.logisticoPage">
<ContentPage.Content>
<cntrl:CustomMap
MapType="Street"
WidthRequest="300"
HeightRequest="300"
MapPosition="{Binding MyPosition}"
MapPins="{Binding AllPines}"
RouteCoordinates="{Binding Ruta}"></cntrl:CustomMap>
</ContentPage.Content>
</ContentPage>
