使用 MKCreateClusterAnnotation Xamarin Forms 显示集群视图

问题描述 投票:0回答:1

如何使用 ios 地图渲染对 pin 结果进行分组或聚类?
我尝试了以下逻辑,但在实现中我感到困惑。
https://github.com/xamarin/ios-samples/blob/main/ios11/MapKitSample/Tandm/ViewController.cs

if (e.NewElement != null)
{
    var formsMap = (InitMap)e.NewElement;
    var nativeMap = Control as MKMapView;
    customPins = formsMap.InitCustomPins;
    
    nativeMap.GetViewForAnnotation = GetViewForAnnotation;
    nativeMap.CreateClusterAnnotation = GetClusterView();
}
[![protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
        {
            MKAnnotationView annotationView = null;
            
            if (annotation is MKUserLocation)
                return null;
            var customPin = GetCustomPins(annotation as MKPointAnnotation);
            //it returns 37 pins . I would like to cluster by item.Id .
            if (customPin == null)
            {
                return null;
            }
        foreach (var item in customPin)
            {
            var clusterThis=item.id  
if ID==1 
{ PAINT THE BUBBLE RED } 
            int clusterSize = GetClusterSize(); // Obtain the cluster size 
            MKCreateClusterAnnotation clusterAnnotation = 
            GetClusterAnnotation(clusterSize); heres what I dont know how to implement .   
            }
}]

xamarin annotations mkpointannotation
1个回答
0
投票

地图标记聚类是iOS11中的新功能。示例 MapKit 示例“Tandm” 展示了如何实现新的 iOS 11 注释聚类功能。

我按照 iOS 11 上 MapKit 的新功能制作了一个演示,并在 MapKit 示例“Tandm”中使用了很多代码。

自定义MapRenderer.cs

if (e.NewElement != null)
        {
            var formsMap = (CustomMap)e.NewElement;             
            //Some differences with the previous thread
            //For performance reasons, I try adding pins natively
            //instead of using data bindings.
            AddPinData();
            LoadDataForMapRegionAndBikes(nativeMap);
            nativeMap.GetViewForAnnotation = GetViewForAnnotation;
        }

添加一些引脚数据后,我们应该将引脚注释添加到我们的nativeMap中。为此,我们定义了一个 MyCustomPin 模型类。

    private void LoadDataForMapRegionAndBikes(MKMapView nativeMap)
    { 
        var pins = new List<MyCustomPin>();
        foreach (PinData data in PinsCollection)
        {            

                NSNumber Lat = data.PinPostion.Latitude;
                NSNumber Lgn = data.PinPostion.Longitude;
                var Id = data.PinId;
                var Label = new NSString(data.PinLabel);
                var Name = new NSString(data.PinName);

                CLLocationCoordinate2D Coordinate = new CLLocationCoordinate2D(Lat.NFloatValue, Lgn.NFloatValue);
                MyCustomPin myCustomPin = new MyCustomPin(Coordinate, Name);
                myCustomPin.Lat = Lat;
                myCustomPin.Lgn = Lgn;
                myCustomPin.Id = Id;
                myCustomPin.Label = Label;
                myCustomPin.Name = Name;
                pins.Add(myCustomPin);
        }
        nativeMap.AddAnnotations(pins.ToArray());
    }

这是 MyCustomPin 类。稍后我们将根据这个 Id 属性来决定 clusteridendifier。

public class MyCustomPin : MKPointAnnotation
{
    public NSNumber Lat { get; set; }
    public NSNumber Lgn { get; set; }
    public int Id { get; set; }
    public NSString Name { get; set; } 
    public NSString Label { get; set; } 
    #region Constructors
    public MyCustomPin()
    {
    }

    public MyCustomPin(CLLocationCoordinate2D cLLocationCoordinate2D,string title) : base(cLLocationCoordinate2D,title,title)
    {


    }
}

GetViewForAnnotation是最重要的方法,我们在其中自定义我们的pin和cluster。 CustomMKAnnotationView继承自MKAnnotationView,它是自定义Pin的可视化表示。

    protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
    {
        if (annotation is MyCustomPin)
        {
            var marker = annotation as MyCustomPin;

            var view = mapView.DequeueReusableAnnotation(marker.Name) as CustomMKAnnotationView;
            if (view == null)
            {
                view = new CustomMKAnnotationView(marker, marker.Name);
                
                if (marker.Id == 45)
                {
                    view.Image = UIImage.FromFile("unicycle.png");

                }
                else if (marker.Id == 67)
                {
                    view.Image = UIImage.FromFile("tricycle.png");
                }
                else
                {
                    view.Image = UIImage.FromFile("pin.png");
                }

            }
            view.CalloutOffset = new CGPoint(0, 0);
            view.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
            view.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
            view.CanShowCallout = true;
            return view;
        }

        else if (annotation is MKClusterAnnotation)
        {
            var cluster = annotation as MKClusterAnnotation;

            var view = mapView.DequeueReusableAnnotation(MKMapViewDefault.ClusterAnnotationViewReuseIdentifier) as ClusterView;
            if (view == null)
            {
                view = new ClusterView(cluster, MKMapViewDefault.ClusterAnnotationViewReuseIdentifier);
            }

            return view;
        }
        else if (annotation != null)
        {
            var unwrappedAnnotation = MKAnnotationWrapperExtensions.UnwrapClusterAnnotation(annotation);

            return GetViewForAnnotation(mapView, unwrappedAnnotation);
        }
        return null;
    }

自定义MKAnnotationView.cs

ClusteringIdentifier – 这控制哪些标记聚集在一起。例如,如果pin id为45,我们将其所有注释视图的ClusteringIdentifier设置为相同的值,例如45。然后它们将被聚类。

public class CustomMKAnnotationView : MKAnnotationView
{
    public string Name { get; set; }

    public string Url { get; set; }

    #region Override Methods
    public override IMKAnnotation Annotation
    {
        get
        {
            return base.Annotation;
        }
        set
        {
            base.Annotation = value;

            var pin = value as MyCustomPin;
            if (pin != null)
            {
                int id = pin.Id;
                switch (id)
                {
                    case 45:
                        DisplayPriority = MKFeatureDisplayPriority.DefaultHigh;
                        ClusteringIdentifier = "45";
                        break;
                    case 67:
                        DisplayPriority = MKFeatureDisplayPriority.DefaultHigh;
                        ClusteringIdentifier = "67";
                        break;
                }
            }
        }
    }
    #endregion


    public CustomMKAnnotationView(IMKAnnotation annotation, string id)
        : base(annotation, id)
    {
    }
}

ClusterView.cs

该类用于自定义集群视图。我们数数,为不同的簇涂上不同的颜色,并在圆圈中绘制文本。

public class ClusterView : MKAnnotationView
{
    #region Static Variables
    public static UIColor UnicycleColor = UIColor.FromRGB(254, 122, 36);
    public static UIColor TricycleColor = UIColor.FromRGB(153, 180, 44);
    #endregion

    #region Computed Properties
    public override IMKAnnotation Annotation
    {
        get
        {
            return base.Annotation;
        }
        set
        {
            base.Annotation = value;

            // TODO: Workaround, the developer should be able to use
            // `value as MKClusterAnnotation` instead of the following 
            // extension method call:
            var cluster = MKAnnotationWrapperExtensions.UnwrapClusterAnnotation(value);
            if (cluster != null)
            {
                var renderer = new UIGraphicsImageRenderer(new CGSize(40, 40));
                var count = cluster.MemberAnnotations.Length;
                //var unicycleCount = CountBikeType(cluster.MemberAnnotations, BikeType.Unicycle);

                Image = renderer.CreateImage((context) => {
                  
                    var customPin = cluster.MemberAnnotations[0] as MyCustomPin;

                    if (customPin.Id == 45)
                    {
                        UnicycleColor.SetFill();
                    }
                    else
                    {
                        TricycleColor.SetFill();
                    }

                    UIBezierPath.FromOval(new CGRect(0, 0, 40, 40)).Fill();

                    
                    var attributes = new UIStringAttributes()
                    {
                        ForegroundColor = UIColor.Black,
                        Font = UIFont.BoldSystemFontOfSize(20)
                    };
                    var text = new NSString($"{count}");
                    var size = text.GetSizeUsingAttributes(attributes);
                    var rect = new CGRect(20 - size.Width / 2, 20 - size.Height / 2, size.Width, size.Height);
                    text.DrawString(rect, attributes);
                });
            }
        }
    }
    #endregion

    #region Constructors
    public ClusterView()
    {
    }

    public ClusterView(NSCoder coder) : base(coder)
    {
    }

    public ClusterView(IntPtr handle) : base(handle)
    {
    }

    public ClusterView(IMKAnnotation annotation, string reuseIdentifier) : base(annotation, reuseIdentifier)
    {
        // Initialize
        DisplayPriority = MKFeatureDisplayPriority.DefaultHigh;
        CollisionMode = MKAnnotationViewCollisionMode.Circle;

        // Offset center point to animate better with marker annotations
        CenterOffset = new CoreGraphics.CGPoint(0, -10);
    }
    #endregion
}

最后就是这个效果了,

© www.soinside.com 2019 - 2024. All rights reserved.