【问题标题】:GetViewForAnnotation returning default red pin after loading custom oneGetViewForAnnotation 在加载自定义后返回默认红色引脚
【发布时间】:2021-08-13 19:42:00
【问题描述】:

我一直在努力使我之前开发的地图集群变得友好,我遇到了一些使用 nugget ClusterKit 的很酷的例子,一切似乎都工作正常,集群去集群明智,但是我已经加载的一些引脚正在恢复为默认值红色别针。我的 Pins 被正确添加并且它们都聚集得很好,但是当我的地图区域发生变化然后返回到以前加载的部分(带有加载的 pin)时,它们几乎总是都恢复为红色的 iOS pin 在做了更多的挖掘之后,最初我的注释作为 Xamarin.iOS.ClusterKit.CKCluster 类型传递给 GetViewForAnnotation(好)但是在“初始加载”之后,引脚将变为红色,因此它不再是 CKCluster 类型,它现在是(默认 MKAnnotationView)这将删除所有集群能力。 地图渲染器

[assembly: ExportRenderer(typeof(CustomMap), typeof(iOSMapRenderer))]

ClusterMap _clusterMap;
MKMapView Map => Control as MKMapView;
CustomMap PCLMap => Element as CustomMap;
_testClustering = true;
protected override void OnElementChanged(ElementChangedEventArgs<CustomMap> e)
{

   base.OnElementChanged(e);

    if (e.OldElement != null && Map != null)
    ...

    if (e.NewElement == null) return;
    if (_testClustering)
    {
      _clusterMap = new ClusterMap(Map);
    }
    if (Map == null) return;
    Map.GetViewForAnnotation = GetViewForAnnotation;
    Map.DidSelectAnnotationView += OnDidSelectAnnotationView;
    Map.RegionChanged += OnMapRegionChanged;
    ...
    UpdatePins(true);
    PCLMap.PropertyChanged += OnMapPropertyChanged;
}

void OnMapPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == CustomMap.Pins)
        UpdatePins();
    else if(e.PropertyName == CustomMap.SelectedPin)
            SetSelectedPin();
    else if(e.PropertyName == CustomMap.MapRegion)
           UpdateMapRegion();
}

void UpdatePins(firstTime)
{
   if (_testClustering)
       {
         _clusterMap.ClusterManager
                  .RemoveAnnotations(_clusterMap.ClusterManager.Annotations);
        }
   else
        {
          Map.RemoveAnnotations(Map.Annotations);
        }

   foreach (var i in PCLMap.Pins)
   {
       i.PropertyChanged -= OnPinPropertyChanged;
       AddPin(i);
   }
   if (firstTime)
   {
       if (PCLMap.Pins is INotifyCollectionChanged observable)
        {
          observable.CollectionChanged += OnCollectionChanged;
        }
    }
}

 void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
  if (e.Action == NotifyCollectionChangedAction.Add)
  {
    foreach (CustomPin pin in e.NewItems)
    {
        AddPin(pin);
    }
  }
  else if (e.Action == NotifyCollectionChangedAction.Reset)
  {
      IEnumerable<IMKAnnotation> annotations = _testClustering ? _clusterMap.ClusterManager.Annotations : Map.Annotations;

      foreach (var annotation in annotations.OfType<MyMapAnnotation>())
      {
         annotation.CustomPin.PropertyChanged -= OnPinPropertyChanged;
      }
      UpdatePins(false);
    }
}

      void AddPin(CustomPin pin)
    {
       var annotation = new MyMapAnnotation(pin);
       if (_testClustering)
       {
          _clusterMap.ClusterManager.AddAnnotation(annotation);
       }
       else
       {
          Map.AddAnnotation(annotation);
       }
    }
    
    public virtual MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
    {
       var clusterAnnotation = annotation as CKCluster;
       var createInitialClusterView = false;
       MKAnnotationView annotationView = null;
       MyMapAnnotation customAnnotation = null;
       if (clusterAnnotation == null)
       {
         //for non clustering map -- 
         //but gets called after initial load because pin is no   
         //Longer recognized as CKCluster
          customAnnotation = annotation as MyMapAnnotation;
       }
       else
       {
         if (clusterAnnotation.Count > 1)
         {
             var clusterPin = PCLMap.GetClusteredPin?.Invoke(null, clusterAnnotation.Annotations.OfType<MyMapAnnotation>().Select(i => i.CustomPin));
             if (clusterPin == null)
             {
                createInitialClusterView = true;
             }
             else
             {
               customAnnotation = new MyMapAnnotation(clusterPin);
             }
         }
         else  
         {
            customAnnotation = clusterAnnotation.FirstAnnotation as MyMapAnnotation;
         }
       }
       // IF we need to create a new cluster
       if (createInitialClusterView)
       {
          
           annotationView = new ClusterAnnotationView(clusterAnnotation, 
          
        else 
        {
           if (customAnnotation == null)
           {
               return null;
           }
    
          if (annotationView == null)
           {
               annotationView = new MKAnnotationView(customAnnotation, 
                                AnnotationIdentifier);
               annotationView.Layer.AnchorPoint = new 
                                       CGPoint(customAnnotation.CustomPin.AnchorPoint.X, 
           }
          else
          {
            annotationView.Annotation = customAnnotation;
          }
          annotationView.CanShowCallout = customAnnotation.CustomPin.ShowCallout;
          SetAnnotationViewVisibility(annotationView, customAnnotation.CustomPin);
          UpdateImage(annotationView, customAnnotation.CustomPin);
                 
        }
        return annotationView; // returning default MKAnnotationView 
    }

聚类图

//initializing example
 public class ClusterMap : CKMap
{
   MKMapView _mkMapView;

public ClusterMap(MKMapView mapView)
{
   _mkMapView = mapView;
}
CKClusterManager mapView;
public override CKClusterManager ClusterManager => LazyInitializer.EnsureInitialized(ref _clusterManager, () =>
{
   _clusterManager = new CKClusterManager();
   _clusterManager.Map = this;
   _clusterManager.Algorithm = new CKNonHierarchicalDistanceBasedAlgorithm();

    return _clusterManager;
 });

public override MKMapRect VisibleMapRect => _mkMapView.VisibleMapRect;

public override void AddClusters(CKCluster[] clusters)
{
   _mkMapView.AddAnnotations(clusters);
}

public override void DeselectCluster(CKCluster cluster, bool animated)
{
   if (! _mkMapView.SelectedAnnotations.Contains(cluster)) return;
   _mkMapView.DeselectAnnotation(cluster, animated);
}

public override void PerformAnimations(CKClusterAnimation[] animations, Action<bool> completion)
{
    foreach (var animation in animations)
    {
       animation.Cluster.Coordinate = animation.From;
    }
  //... performs clustering animation
}

public override void RemoveClusters(CKCluster[] clusters)
{
    _mkMapView.RemoveAnnotations(clusters);
}

public override void SelectCluster(CKCluster cluster, bool animated)
{
   //TODO Zoom in
}

 public MKMapRect MKMapRectByAddingPoint(MKMapRect rect, MKMapPoint point)
{
    return MKMapRect.Union(rect, new MKMapRect() { Origin = point, Size = MKMapRect.Null.Size });
}

MyMapAnnotation

internal class MyMapAnnotation : MKAnnotation
{
   CLLocationCoordinate2D _coordinate;
   readonly CustomPin _formsPin;
  public override string Title
  {
     get
     {
       return _formsPin.Label;
      }
   }

 public override CLLocationCoordinate2D Coordinate
 {
    get { return _coordinate; }
 }

 public CustomPin CustomPin
 {
    get { return _formsPin; }
 }

 public override void SetCoordinate(CLLocationCoordinate2D value)
 {
    if (!value.IsValid()) return;
    _formsPin.Position = value.ToPosition();
    _coordinate = value;
 }

  public void SetCoordinateOriginal(CLLocationCoordinate2D value)
  {
    SetCoordinate(value);
  }

  public MyMapAnnotation(CustomPin pin)
  {
    _formsPin = pin;
    _coordinate = pin.Position.ToLocationCoordinate();
    _formsPin.PropertyChanged += FormsPinPropertyChanged;
  }
 public void SetCoordinateInternal(CLLocationCoordinate2D value, bool triggerObserver)
 {
    if (triggerObserver)
         WillChangeValue("coordinate");
    SetCoordinate(value);
    if (triggerObserver)
        DidChangeValue("coordinate");
  }
 System.ComponentModel.PropertyChangedEventArgs e)
 {
    if (e.PropertyName == nameof(CustomPin.Label))
    {
        WillChangeValue("title");
        DidChangeValue("title");
    }
 }

 protected override void Dispose(bool disposing)
 {
    base.Dispose(disposing);
    if (disposing)
       _formsPin.PropertyChanged -= FormsPinPropertyChanged;
  }

}

【问题讨论】:

    标签: ios xamarin


    【解决方案1】:

    想通了。打开我的 GetViewForAnnotation 中的问题。我的注释被封装到 AnnotationWrapper 而不是注释中。然后,这阻止了我在我的情况下将任何内容转换为我的 CustomAnnotationView。我最终引用了 NSObject 并且引用了 CKCluster 项(原始类型)。然后我对方法的流程做了一些调整,但我能够得到我需要的东西,现在一切正常。我得到了一些帮助,但我希望不再需要 Xamarin 的帮助,因为它很快就会被弃用。阿门。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-05
      • 2013-11-14
      • 2020-06-20
      • 1970-01-01
      • 2016-08-24
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      相关资源
      最近更新 更多