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>

 

 

 

Artículos relacionados
Cómo crear Mapas bindable en Xamarin.Forms (Parte 3)
Cómo crear Mapas bindable en Xamarin.Forms (Parte 3)

Si estas desarrollando una plicación Xamarin.F

Cómo crear Mapas bindable en Xamarin.Forms (Parte 1)
Cómo crear Mapas bindable en Xamarin.Forms (Parte 1)

Si estas desarrollando una plicación Xamarin.F

Cómo crear Mapas bindable en Xamarin.Forms (Parte 2)
Cómo crear Mapas bindable en Xamarin.Forms (Parte 2)

Si estas desarrollando una plicación Xamarin.F

2 Comentarios
  • Jesus Padilla Comentar
    martes, 14 de agosto de 2018

    Excelente tutorial, muchas gracias, Tengo una duda , el codigo no me tiro ningun error, pero debugueando veo que me carga la ruta y va al custom map render pero no trae nada, no esta pasando por el CustomMap.cs donde se manda llamar esa clase para poder pasarle la lista de rutas?

  • Jose Comentar
    martes, 14 de agosto de 2018

    No entiendo cuál es tu problema, puedes compartir imágenes para ver el problema. Al correo info@estradawebgroup.com

Enviame un comentario