Xamarin表单-使用自定义地图渲染器的地图上的多个多边形

Bar*_*ers 2 c# xamarin.ios xamarin xamarin.forms

我已经遵循 Xamarin表单教程,教程使用自定义地图渲染器突出显示地图上的区域。本教程介绍了如何在Xamarin Forms中向地图添加一个多边形,但没有说明如何扩展代码以在地图上允许多个多边形。

如何调整此实现以在iOS的地图上允许多个多边形?这是我的iOS代码:

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.iOS
{
    public class CustomMapRenderer : MapRenderer
    {
        MKPolygonRenderer polygonRenderer;

        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;
                    polygonRenderer = null;
                }
            }

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

                nativeMap.OverlayRenderer = GetOverlayRenderer;

                CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[formsMap.ShapeCoordinates.Count];

                int index = 0;
                foreach (var position in formsMap.ShapeCoordinates)
                {
                    coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
                    index++;
                }

                var blockOverlay = MKPolygon.FromCoordinates(coords);
                nativeMap.AddOverlay(blockOverlay);
            }
        }




 MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
      {
          if (polygonRenderer == null && !Equals(overlayWrapper, null)) {
              var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
              polygonRenderer = new MKPolygonRenderer(overlay as MKPolygon) {
                  FillColor = UIColor.Red,
                  StrokeColor = UIColor.Blue,
                  Alpha = 0.4f,
                  LineWidth = 9
              };
          }
          return polygonRenderer;
      }

    }
}
Run Code Online (Sandbox Code Playgroud)

Kev*_* Li 5

您的代码有两个问题:

  1. 第一个问题在您的if (e.NewElement != null){...}代码中。如果要具有多个多边形,formsMap.ShapeCoordinates则应为一种List<List<Position>>。因此它可以具有多个面的坐标组。如您的代码所示,它使用List<Position>。而且您的代码nativeMap.AddOverlay(blockOverlay);仅触发一次,这只会在地图中添加一个叠加层。

  2. 更改if (polygonRenderer == null && !Equals(overlayWrapper, null))GetOverlayRendererif (!Equals(overlayWrapper, null))。否则,每次地图添加叠加层并触发方法时,它将返回first polygonRenderer

这是我的代码,例如:

  1. PCL 中MainPage.xaml中的代码:

    <ContentPage.Content>
        <local:CustomMap x:Name="customMap" MapType="Street" WidthRequest="{x:Static local:App.ScreenWidth}" HeightRequest="{x:Static local:App.ScreenHeight}" />
    </ContentPage.Content>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我在PCL的MainPage.xaml.cs中添加了两个多边形的位置列表:

    List<Position> pos = new List<Position> { new Position(39.939889, 116.423493), new Position(39.930622, 116.423924), new Position(39.930733,116.441135), new Position(39.939944, 116.44056) };
    List<Position> posi = new List<Position> { new Position(39.934633, 116.399921), new Position(39.929709, 116.400208), new Position(39.929792, 116.405994), new Position(39.934689,116.405526) };
    customMap.ShapeCoordinates.Add(pos);
    customMap.ShapeCoordinates.Add(posi);
    customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(39.934689, 116.405526), Distance.FromMiles(1.5)));
    
    Run Code Online (Sandbox Code Playgroud)
  3. PCL 中CustomMap.cs中的代码:

    public class CustomMap : Map
    {
        public List<List<Position>> ShapeCoordinates { get; set; }
    
        public CustomMap()
        {
            ShapeCoordinates = new List<List<Position>>();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. iOS平台中CustomMapRenderer.cs中的代码:

    class CustomMapRenderer : MapRenderer
    {
        MKPolygonRenderer polygonRenderer;
    
        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;
                    polygonRenderer = null;
                }
            }
    
            if (e.NewElement != null)
            {
                var formsMap = (CustomMap)e.NewElement;
                var nativeMap = Control as MKMapView;
                nativeMap.OverlayRenderer = GetOverlayRenderer;
    
                foreach (List<Position> positionList in formsMap.ShapeCoordinates)
                {
    
                    CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[positionList.Count];
    
                    int index = 0;
                    foreach (var position in positionList)
                    {
                        coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
                        Console.WriteLine(position.Latitude +" : "+ position.Longitude);
    
                        index++;
                    }
    
    
    
                    var blockOverlay = MKPolygon.FromCoordinates(coords);
                    nativeMap.AddOverlay(blockOverlay);
    
                }
            }
        }
    
    
    
        MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
        {
            if (!Equals(overlayWrapper, null))
            {         
                var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
                polygonRenderer = new MKPolygonRenderer(overlay as MKPolygon)
                {
                    FillColor = UIColor.Red,
                    StrokeColor = UIColor.Blue,
                    Alpha = 0.4f,
                    LineWidth = 9
    
                };
            }
            return polygonRenderer;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

它是这样的:

在此处输入图片说明