xamarin ios 折线 Map.AddOverlay 无效

xamarin ios polyline Map.AddOverlay not works

我正在尝试在地图上绘制一条用户走过的路径。它在 android 上运行良好,但在 ios 上运行良好,只需在起始小线处绘制即可。 "OnElementPropertyChanged"触发后不绘制任何东西。

RouteCoordinates 在基于 CustomMap 的地图 class 上创建为 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;
    }
}
}

我这边试过后,发现如果要在iOS的地图中刷新折线,必须:

  1. 删除旧的 polyline;
  2. 每次都使用一个新的 nativeMap.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;
            });

我也上传了我的演示here,你可以看看。让我知道它是否有效。