如何使用 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 .
}
}]
地图标记聚类是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
}
最后就是这个效果了,