xamarin ios polyline Map.AddOverlay не работает - PullRequest
0 голосов
/ 27 мая 2019

Я пытаюсь нарисовать на карте путь, по которому ходил пользователь.Он отлично работает на Android, но IOS, просто начните рисовать небольшую линию.После срабатывания «OnElementPropertyChanged» ничего не рисуется.

Координаты RouteCoordinates создаются в классе Map на основе CustomMap как BindableProperties.Я думаю, что мой метод измененного свойства не может достигнуть правильного слоя отображения или потока.

Мой пользовательский рендер для IOS:

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace PawsApp.iOS.Renderers
{
    public class CustomMapRenderer : MapRenderer
    {
        MKPolylineRenderer polylineRenderer;
        CustomMap formsMap;
        MKMapView nativeMap;

    protected override void OnElementChanged(ElementChangedEventArgs<View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            if (nativeMap != null)
            {
                nativeMap.RemoveOverlays(nativeMap.Overlays);
                nativeMap.OverlayRenderer = null;
                polylineRenderer = null;
            }
        }

        if (e.NewElement != null)
        {
            formsMap = (CustomMap)e.NewElement;
            nativeMap = Control as MKMapView;
            UpdatePolyLine();
        }
    }

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (this.Element == null || this.Control == null)
            return;

        //if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
        if ((e.PropertyName == "RouteCoordinates" || e.PropertyName == "VisibleRegion"))
        {
            formsMap = (CustomMap)sender;
            nativeMap = Control as MKMapView;
            UpdatePolyLine();               
        }
    }


    private void UpdatePolyLine()
    {

        //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);
    }


    //[Foundation.Export("mapView:rendererForOverlay:")]
    MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
    {
        if (polylineRenderer == null)
        {
            var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
            //var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as MKPolyline;
            polylineRenderer = new MKPolylineRenderer(overlay as MKPolyline)
            {
                FillColor = UIColor.Yellow,
                StrokeColor = UIColor.Red,
                LineWidth = 3,
                Alpha = 0.4f
            };
        }
        return polylineRenderer;
    }
}
}

1 Ответ

1 голос
/ 29 мая 2019

Попробовав это на моей стороне, я обнаружил, что если вы хотите обновить polyLine на Карте в iOS, вам необходимо:

  1. удалить старую polyline;
  2. используйте новый n ativeMap.OverlayRenderer каждый раз.

Я изменил код рендера клиента следующим образом:

public class CustomMapRenderer : MapRenderer
{
    MKPolylineRenderer polylineRenderer;
    CustomMap formsMap;
    MKMapView nativeMap;

    MKPolyline polyline;

    protected override void OnElementChanged(ElementChangedEventArgs<View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            if (nativeMap != null)
            {
                nativeMap.RemoveOverlays(nativeMap.Overlays);
                nativeMap.OverlayRenderer = null;
                polylineRenderer = null;
            }
        }

        if (e.NewElement != null)
        {
            formsMap = (CustomMap)e.NewElement;
            nativeMap = Control as MKMapView;
            UpdatePolyLine();
        }
    }

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (this.Element == null || this.Control == null)
            return;

        //if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
        if ((e.PropertyName == "RouteCoordinates" || e.PropertyName == "VisibleRegion"))
        {
            formsMap = (CustomMap)sender;
            nativeMap = Control as MKMapView;
            UpdatePolyLine();
        }

    }


    private void UpdatePolyLine()
    {

        //var nativeMap = Control as MKMapView;

        if (polyline != null)
        {
            nativeMap.RemoveOverlay(polyline);
            polyline.Dispose();
        }

        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);

        polyline = routeOverlay;
    }


    //[Foundation.Export("mapView:rendererForOverlay:")]
    MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
    {
        if (polylineRenderer != null)
        {
            polylineRenderer = null;
        }

        var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
        //var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as MKPolyline;

        polylineRenderer = new MKPolylineRenderer(overlay as MKPolyline)
        {
            FillColor = UIColor.Yellow,
            StrokeColor = UIColor.Red,
            LineWidth = 3,
            Alpha = 0.4f
        };

        return polylineRenderer;
    }
}

И в части xamarin.forms сбросьте customMap.RouteCoordinatesкаждый раз:

  Device.StartTimer(TimeSpan.FromSeconds(3), () =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                          a -= 0.000321;
                          b += 0.000222;
                          customMap.RouteCoordinates = new List<Position>
                          {
                              new Position (37.797534, -122.401827),
                              new Position(37.797510, -122.402060),
                              new Position(37.790269, -122.400589),
                              new Position(37.790265, -122.400474),
                              new Position(37.790228, -122.400391),
                              new Position(37.790126, -122.400360),
                              new Position(37.789250, -122.401451),
                              new Position(a, b)
                          };
                });

            return true;
            });

Я также загружаю демо здесь , и вы можете проверить его.Дайте мне знать, если это работает.

...