How to animate a polyline in a map (iOS)?

Hi! I',m developing an application in Xamarin Forms and based on the examples of Xamarin Forms i did this:

https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/maps/map-overlay/polyline/

And I modify the CustomMapRender.cs class in android project:

using System.Collections.Generic;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using MapOverlay;
using MapOverlay.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using System.Threading.Tasks;

[assembly:ExportRenderer (typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.Droid
{
public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
{
GoogleMap map;
List routeCoordinates;

    protected override void OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs<View> e)
    {
        base.OnElementChanged (e);

        if (e.OldElement != null) {
            // Unsubscribe
        }

        if (e.NewElement != null) {
            var formsMap = (CustomMap)e.NewElement;
            routeCoordinates = formsMap.RouteCoordinates;

            ((MapView)Control).GetMapAsync (this);
        }
    }

    public void OnMapReady (GoogleMap googleMap)
    {
        map = googleMap;

        var polylineOptions = new PolylineOptions ();
        polylineOptions.InvokeColor (0x66FF0000);

        foreach (var position in routeCoordinates) {
            polylineOptions.Add (new LatLng (position.Latitude, position.Longitude));
            await Task.Delay(30);
        }

        map.AddPolyline (polylineOptions);
    }
}

}

In Android, the Delay in the foreach animate the polyline, and the idea is that animating the polyline you can see the direction of the route.

But, I want to do the same in iOS project, but I don't know how to implement the same idea. I have the code that show the route, is the same class, CustomMapRenderer.cs

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;
            nativeMap.OverlayRenderer = 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);
        }
    }

    MKOverlayRenderer GetOverlayRenderer (MKMapView mapView, IMKOverlay overlay)
    {
        if (polylineRenderer == null) {
            polylineRenderer = new MKPolylineRenderer (overlay as MKPolyline);
            polylineRenderer.FillColor = UIColor.Blue;
            polylineRenderer.StrokeColor = UIColor.Red;
            polylineRenderer.LineWidth = 3;
            polylineRenderer.Alpha = 0.4f;
        }
        return polylineRenderer;
    }
}

}

Any idea of how I can do this?

Thank you and regards from Mexico.

Answers

  • SeekerSeeker Member

    I have done something like this, you can change it according to your need. And don't forget to share your enhanced code here for others.

    using System;
    using CoreLocation;
    using MapKit;
    using UIKit;
    using System.Collections.Generic;
    using Foundation;
    using System.Threading.Tasks;

    namespace Tracker
    {

    public partial class ViewController : UIViewController
    {
        public static LocationManager Manager { get; set; }
        public MKPolyline polyline;
        public List<CLLocationCoordinate2D> coordinates = new List<CLLocationCoordinate2D>();
    
        //public MKPlacemark sourcePlacemark;
        //public MKPlacemark destinationPlacemark;
        private MKMapViewDelegate _mapDelegate;
    
        MKCoordinateRegion region;
        MKCoordinateSpan span;
    
        protected ViewController(IntPtr handle) : base(handle)
        {
        }
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            //Manager = new LocationManager();
            //Manager.StartLocationUpdates();
    
    
            mapView.ShowsUserLocation = false;
    
            //Create new MapDelegate Instance
            _mapDelegate = new MapDelegate();
            mapView.Delegate = _mapDelegate;
    
            // create an array of coordinates from allPins
            coordinates.Add(new CLLocationCoordinate2D(37.092460, -95.710443));
            coordinates.Add(new CLLocationCoordinate2D(39.70665841, -104.79103088));
            coordinates.Add(new CLLocationCoordinate2D(39.70692253, -104.79884148));
            coordinates.Add(new CLLocationCoordinate2D(39.70877139, -104.80871201));
            coordinates.Add(new CLLocationCoordinate2D(39.7085733, -104.81017113));
            coordinates.Add(new CLLocationCoordinate2D(39.70474346, -104.8100853));
            coordinates.Add(new CLLocationCoordinate2D(39.70022001, -104.80991364));
            coordinates.Add(new CLLocationCoordinate2D(39.69658783, -104.80999947));
            coordinates.Add(new CLLocationCoordinate2D(39.69602648, -104.80995655));
            coordinates.Add(new CLLocationCoordinate2D(39.68684604, -104.81025696));
            coordinates.Add(new CLLocationCoordinate2D(39.68592133, -104.80390549));
            coordinates.Add(new CLLocationCoordinate2D(39.68605343, -104.7927475));
            coordinates.Add(new CLLocationCoordinate2D(39.68555804, -104.78369236));
            coordinates.Add(new CLLocationCoordinate2D(39.68284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68584986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68784986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68984986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69084986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69484986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69884986, -104.78154659));
        }
    
    
        #region Public Methods
    
        //private void drawLine(CLLocation location)
        private async System.Threading.Tasks.Task drawLineAsync()
        {
    
            List<CLLocationCoordinate2D> newlist = new List<CLLocationCoordinate2D>();
            foreach (var cord in coordinates)
            {
                if (this.polyline != null)
                {
                    mapView.RemoveOverlay(this.polyline);
                }
    
                region.Center.Latitude = cord.Latitude;
                region.Center.Longitude = cord.Longitude;
    
                //region.Center = mapView.UserLocation.Coordinate;
    
                span.LatitudeDelta = 0.05;     // 0.001
                span.LongitudeDelta = 0.05;
                region.Span = span;
                mapView.SetRegion(region, true);
    
                // create a polyline with all cooridnates
                if (coordinates.IndexOf(cord) != 0)
                {
                    newlist.Add(coordinates[coordinates.IndexOf(cord) - 1]);
                }
    
                newlist.Add(cord);
                polyline = MKPolyline.FromCoordinates(newlist.ToArray() as CLLocationCoordinate2D[]);
                mapView.AddOverlay(polyline);
                await Task.Delay(500);
            }
        }
    
    
        partial void btnUpdateLocationTapped(NSObject sender)
        {
            drawLineAsync();
        }
    
        #endregion
    }
    
    class MapDelegate : MKMapViewDelegate
    {
        //Override OverLayRenderer to draw Polyline from directions
        public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay)
        {
            if (overlay is MKPolyline)
            {
                var route = (MKPolyline)overlay;
                var renderer = new MKPolylineRenderer(route) { StrokeColor = UIColor.Blue };
                return renderer;
            }
            return null;
        }
    }
    

    }

  • SeekerSeeker Member

    using System;
    using CoreLocation;
    using MapKit;
    using UIKit;
    using System.Collections.Generic;
    using Foundation;
    using System.Threading.Tasks;

    namespace Tracker
    {

    public partial class ViewController : UIViewController
    {
        public static LocationManager Manager { get; set; }
        public MKPolyline polyline;
        public List<CLLocationCoordinate2D> coordinates = new List<CLLocationCoordinate2D>();
    
        //public MKPlacemark sourcePlacemark;
        //public MKPlacemark destinationPlacemark;
        private MKMapViewDelegate _mapDelegate;
    
        MKCoordinateRegion region;
        MKCoordinateSpan span;
    
        protected ViewController(IntPtr handle) : base(handle)
        {
        }
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            //Manager = new LocationManager();
            //Manager.StartLocationUpdates();
    
    
            mapView.ShowsUserLocation = false;
    
            //Create new MapDelegate Instance
            _mapDelegate = new MapDelegate();
            mapView.Delegate = _mapDelegate;
    
            // create an array of coordinates from allPins
            coordinates.Add(new CLLocationCoordinate2D(37.092460, -95.710443));
            coordinates.Add(new CLLocationCoordinate2D(39.70665841, -104.79103088));
            coordinates.Add(new CLLocationCoordinate2D(39.70692253, -104.79884148));
            coordinates.Add(new CLLocationCoordinate2D(39.70877139, -104.80871201));
            coordinates.Add(new CLLocationCoordinate2D(39.7085733, -104.81017113));
            coordinates.Add(new CLLocationCoordinate2D(39.70474346, -104.8100853));
            coordinates.Add(new CLLocationCoordinate2D(39.70022001, -104.80991364));
            coordinates.Add(new CLLocationCoordinate2D(39.69658783, -104.80999947));
            coordinates.Add(new CLLocationCoordinate2D(39.69602648, -104.80995655));
            coordinates.Add(new CLLocationCoordinate2D(39.68684604, -104.81025696));
            coordinates.Add(new CLLocationCoordinate2D(39.68592133, -104.80390549));
            coordinates.Add(new CLLocationCoordinate2D(39.68605343, -104.7927475));
            coordinates.Add(new CLLocationCoordinate2D(39.68555804, -104.78369236));
            coordinates.Add(new CLLocationCoordinate2D(39.68284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68584986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68784986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68984986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69084986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69484986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69884986, -104.78154659));
        }
    
    
        #region Public Methods
    
        //private void drawLine(CLLocation location)
        private async System.Threading.Tasks.Task drawLineAsync()
        {
    
            List<CLLocationCoordinate2D> newlist = new List<CLLocationCoordinate2D>();
            foreach (var cord in coordinates)
            {
                if (this.polyline != null)
                {
                    mapView.RemoveOverlay(this.polyline);
                }
    
                region.Center.Latitude = cord.Latitude;
                region.Center.Longitude = cord.Longitude;
    
                //region.Center = mapView.UserLocation.Coordinate;
    
                span.LatitudeDelta = 0.05;     // 0.001
                span.LongitudeDelta = 0.05;
                region.Span = span;
                mapView.SetRegion(region, true);
    
                // create a polyline with all cooridnates
                if (coordinates.IndexOf(cord) != 0)
                {
                    newlist.Add(coordinates[coordinates.IndexOf(cord) - 1]);
                }
    
                newlist.Add(cord);
                polyline = MKPolyline.FromCoordinates(newlist.ToArray() as CLLocationCoordinate2D[]);
                mapView.AddOverlay(polyline);
                await Task.Delay(500);
            }
        }
    
    
        partial void btnUpdateLocationTapped(NSObject sender)
        {
            drawLineAsync();
        }
    
        #endregion
    }
    
    class MapDelegate : MKMapViewDelegate
    {
        //Override OverLayRenderer to draw Polyline from directions
        public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay)
        {
            if (overlay is MKPolyline)
            {
                var route = (MKPolyline)overlay;
                var renderer = new MKPolylineRenderer(route) { StrokeColor = UIColor.Blue };
                return renderer;
            }
            return null;
        }
    }
    

    }

    Regards Musaab Qamar

  • SeekerSeeker Member

    I have done something like this, you can change it according to your need. And don't forget to share your enhanced code here for others.

    using System;
    using CoreLocation;
    using MapKit;
    using UIKit;
    using System.Collections.Generic;
    using Foundation;
    using System.Threading.Tasks;

    namespace Tracker
    {

    public partial class ViewController : UIViewController
    {
        public static LocationManager Manager { get; set; }
        public MKPolyline polyline;
        public List<CLLocationCoordinate2D> coordinates = new List<CLLocationCoordinate2D>();
    
        //public MKPlacemark sourcePlacemark;
        //public MKPlacemark destinationPlacemark;
        private MKMapViewDelegate _mapDelegate;
    
        MKCoordinateRegion region;
        MKCoordinateSpan span;
    
        protected ViewController(IntPtr handle) : base(handle)
        {
        }
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            //Manager = new LocationManager();
            //Manager.StartLocationUpdates();
    
    
            mapView.ShowsUserLocation = false;
    
            //Create new MapDelegate Instance
            _mapDelegate = new MapDelegate();
            mapView.Delegate = _mapDelegate;
    
            // create an array of coordinates from allPins
            coordinates.Add(new CLLocationCoordinate2D(37.092460, -95.710443));
            coordinates.Add(new CLLocationCoordinate2D(39.70665841, -104.79103088));
            coordinates.Add(new CLLocationCoordinate2D(39.70692253, -104.79884148));
            coordinates.Add(new CLLocationCoordinate2D(39.70877139, -104.80871201));
            coordinates.Add(new CLLocationCoordinate2D(39.7085733, -104.81017113));
            coordinates.Add(new CLLocationCoordinate2D(39.70474346, -104.8100853));
            coordinates.Add(new CLLocationCoordinate2D(39.70022001, -104.80991364));
            coordinates.Add(new CLLocationCoordinate2D(39.69658783, -104.80999947));
            coordinates.Add(new CLLocationCoordinate2D(39.69602648, -104.80995655));
            coordinates.Add(new CLLocationCoordinate2D(39.68684604, -104.81025696));
            coordinates.Add(new CLLocationCoordinate2D(39.68592133, -104.80390549));
            coordinates.Add(new CLLocationCoordinate2D(39.68605343, -104.7927475));
            coordinates.Add(new CLLocationCoordinate2D(39.68555804, -104.78369236));
            coordinates.Add(new CLLocationCoordinate2D(39.68284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68584986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68784986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68984986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69084986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69484986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69884986, -104.78154659));
        }
    
    
        #region Public Methods
    
        //private void drawLine(CLLocation location)
        private async System.Threading.Tasks.Task drawLineAsync()
        {
    
            List<CLLocationCoordinate2D> newlist = new List<CLLocationCoordinate2D>();
            foreach (var cord in coordinates)
            {
                if (this.polyline != null)
                {
                    mapView.RemoveOverlay(this.polyline);
                }
    
                region.Center.Latitude = cord.Latitude;
                region.Center.Longitude = cord.Longitude;
    
                //region.Center = mapView.UserLocation.Coordinate;
    
                span.LatitudeDelta = 0.05;     // 0.001
                span.LongitudeDelta = 0.05;
                region.Span = span;
                mapView.SetRegion(region, true);
    
                // create a polyline with all cooridnates
                if (coordinates.IndexOf(cord) != 0)
                {
                    newlist.Add(coordinates[coordinates.IndexOf(cord) - 1]);
                }
    
                newlist.Add(cord);
                polyline = MKPolyline.FromCoordinates(newlist.ToArray() as CLLocationCoordinate2D[]);
                mapView.AddOverlay(polyline);
                await Task.Delay(500);
            }
        }
    
    
        partial void btnUpdateLocationTapped(NSObject sender)
        {
            drawLineAsync();
        }
    
        #endregion
    }
    
    class MapDelegate : MKMapViewDelegate
    {
        //Override OverLayRenderer to draw Polyline from directions
        public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay)
        {
            if (overlay is MKPolyline)
            {
                var route = (MKPolyline)overlay;
                var renderer = new MKPolylineRenderer(route) { StrokeColor = UIColor.Blue };
                return renderer;
            }
            return null;
        }
    }
    

    }

  • SeekerSeeker Member

    using System;
    using CoreLocation;
    using MapKit;
    using UIKit;
    using System.Collections.Generic;
    using Foundation;
    using System.Threading.Tasks;

    namespace Tracker
    {

    public partial class ViewController : UIViewController
    {
        public static LocationManager Manager { get; set; }
        public MKPolyline polyline;
        public List<CLLocationCoordinate2D> coordinates = new List<CLLocationCoordinate2D>();
    
        //public MKPlacemark sourcePlacemark;
        //public MKPlacemark destinationPlacemark;
        private MKMapViewDelegate _mapDelegate;
    
        MKCoordinateRegion region;
        MKCoordinateSpan span;
    
        protected ViewController(IntPtr handle) : base(handle)
        {
        }
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            //Manager = new LocationManager();
            //Manager.StartLocationUpdates();
    
    
            mapView.ShowsUserLocation = false;
    
            //Create new MapDelegate Instance
            _mapDelegate = new MapDelegate();
            mapView.Delegate = _mapDelegate;
    
            // create an array of coordinates from allPins
            coordinates.Add(new CLLocationCoordinate2D(37.092460, -95.710443));
            coordinates.Add(new CLLocationCoordinate2D(39.70665841, -104.79103088));
            coordinates.Add(new CLLocationCoordinate2D(39.70692253, -104.79884148));
            coordinates.Add(new CLLocationCoordinate2D(39.70877139, -104.80871201));
            coordinates.Add(new CLLocationCoordinate2D(39.7085733, -104.81017113));
            coordinates.Add(new CLLocationCoordinate2D(39.70474346, -104.8100853));
            coordinates.Add(new CLLocationCoordinate2D(39.70022001, -104.80991364));
            coordinates.Add(new CLLocationCoordinate2D(39.69658783, -104.80999947));
            coordinates.Add(new CLLocationCoordinate2D(39.69602648, -104.80995655));
            coordinates.Add(new CLLocationCoordinate2D(39.68684604, -104.81025696));
            coordinates.Add(new CLLocationCoordinate2D(39.68592133, -104.80390549));
            coordinates.Add(new CLLocationCoordinate2D(39.68605343, -104.7927475));
            coordinates.Add(new CLLocationCoordinate2D(39.68555804, -104.78369236));
            coordinates.Add(new CLLocationCoordinate2D(39.68284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68584986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68784986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.68984986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69084986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69284986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69484986, -104.78154659));
            coordinates.Add(new CLLocationCoordinate2D(39.69884986, -104.78154659));
        }
    
    
        #region Public Methods
    
        //private void drawLine(CLLocation location)
        private async System.Threading.Tasks.Task drawLineAsync()
        {
    
            List<CLLocationCoordinate2D> newlist = new List<CLLocationCoordinate2D>();
            foreach (var cord in coordinates)
            {
                if (this.polyline != null)
                {
                    mapView.RemoveOverlay(this.polyline);
                }
    
                region.Center.Latitude = cord.Latitude;
                region.Center.Longitude = cord.Longitude;
    
                //region.Center = mapView.UserLocation.Coordinate;
    
                span.LatitudeDelta = 0.05;     // 0.001
                span.LongitudeDelta = 0.05;
                region.Span = span;
                mapView.SetRegion(region, true);
    
                // create a polyline with all cooridnates
                if (coordinates.IndexOf(cord) != 0)
                {
                    newlist.Add(coordinates[coordinates.IndexOf(cord) - 1]);
                }
    
                newlist.Add(cord);
                polyline = MKPolyline.FromCoordinates(newlist.ToArray() as CLLocationCoordinate2D[]);
                mapView.AddOverlay(polyline);
                await Task.Delay(500);
            }
        }
    
    
        partial void btnUpdateLocationTapped(NSObject sender)
        {
            drawLineAsync();
        }
    
        #endregion
    }
    
    class MapDelegate : MKMapViewDelegate
    {
        //Override OverLayRenderer to draw Polyline from directions
        public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay)
        {
            if (overlay is MKPolyline)
            {
                var route = (MKPolyline)overlay;
                var renderer = new MKPolylineRenderer(route) { StrokeColor = UIColor.Blue };
                return renderer;
            }
            return null;
        }
    }
    

    }

    Regards Musaab Qamar

Sign In or Register to comment.