Neue Features in MapKit unter iOS 11

iOS 11 fügt MapKit die folgenden neuen Features hinzu:

Karte mit gruppierten Markern und Kompasstaste

Automatisches Gruppieren von Markern beim Zoomen

Das MapKit-Beispiel "Tandm" zeigt, wie Sie das neue Feature für das Clustering von iOS 11-Anmerkungen implementieren.

1. Erstellen einer MKPointAnnotation Unterklasse

Die Punktanmerkungsklasse stellt jeden Marker auf der Karte dar. Sie können einzeln mithilfe MapView.AddAnnotation() von oder aus einem Array mit MapView.AddAnnotations()hinzugefügt werden.

Punktanmerkungsklassen verfügen nicht über eine visuelle Darstellung, sie müssen nur die Daten darstellen, die dem Marker zugeordnet sind (vor allem die Eigenschaft, die Coordinate ihren Breiten- und Längengrad auf der Karte darstellt) und alle benutzerdefinierten Eigenschaften:

public class Bike : MKPointAnnotation
{
  public BikeType Type { get; set; } = BikeType.Tricycle;
  public Bike(){}
  public Bike(NSNumber lat, NSNumber lgn, NSNumber type)
  {
    Coordinate = new CLLocationCoordinate2D(lat.NFloatValue, lgn.NFloatValue);
    switch(type.NUIntValue) {
      case 0:
        Type = BikeType.Unicycle;
        break;
      case 1:
        Type = BikeType.Tricycle;
        break;
    }
  }
}

2. Erstellen einer MKMarkerAnnotationView Unterklasse für einzelne Marker

Die Markeranmerkungsansicht ist die visuelle Darstellung jeder Anmerkung und wird mithilfe von Eigenschaften wie folgenden formatiert:

  • MarkerTintColor : Die Farbe für den Marker.
  • GlyphText – Text, der im Marker angezeigt wird.
  • GlyphImage : Legt das Bild fest, das im Marker angezeigt wird.
  • DisplayPriority : Bestimmt die Z-Reihenfolge (Stapelverhalten), wenn die Karte mit Markern überlastet ist. Verwenden Sie eine von Required, DefaultHighoder DefaultLow.

Um das automatische Clustering zu unterstützen, müssen Sie auch Folgendes festlegen:

  • ClusteringIdentifier : Hiermit wird gesteuert, welche Marker gruppiert werden. Sie können denselben Bezeichner für alle Ihre Marker verwenden oder unterschiedliche Bezeichner verwenden, um die Art und Weise zu steuern, wie sie gruppiert werden.
[Register("BikeView")]
public class BikeView : MKMarkerAnnotationView
{
  public static UIColor UnicycleColor = UIColor.FromRGB(254, 122, 36);
  public static UIColor TricycleColor = UIColor.FromRGB(153, 180, 44);
  public override IMKAnnotation Annotation
  {
    get {
      return base.Annotation;
    }
    set {
      base.Annotation = value;

      var bike = value as Bike;
      if (bike != null){
        ClusteringIdentifier = "bike";
        switch(bike.Type){
          case BikeType.Unicycle:
            MarkerTintColor = UnicycleColor;
            GlyphImage = UIImage.FromBundle("Unicycle");
            DisplayPriority = MKFeatureDisplayPriority.DefaultLow;
            break;
          case BikeType.Tricycle:
            MarkerTintColor = TricycleColor;
            GlyphImage = UIImage.FromBundle("Tricycle");
            DisplayPriority = MKFeatureDisplayPriority.DefaultHigh;
            break;
        }
      }
    }
  }

3. Erstellen eines MKAnnotationView zum Darstellen von Markerclustern

Während die Anmerkungsansicht, die einen Markercluster darstellt, ein einfaches Bild sein kann , erwarten Benutzer, dass die App visuelle Hinweise dazu liefert, wie viele Marker gruppiert wurden.

Der Beispielcode verwendet CoreGraphics, um die Anzahl der Marker im Cluster sowie eine Kreisdiagrammdarstellung des Anteils jedes Markertyps zu rendern.

Sie sollten auch Folgendes festlegen:

  • DisplayPriority : Bestimmt die Z-Reihenfolge (Stapelverhalten), wenn die Karte mit Markern überlastet ist. Verwenden Sie eine von Required, DefaultHighoder DefaultLow.
  • CollisionModeCircle oder Rectangle.
[Register("ClusterView")]
public class ClusterView : MKAnnotationView
{
  public static UIColor ClusterColor = UIColor.FromRGB(202, 150, 38);
  public override IMKAnnotation Annotation
  {
    get {
      return base.Annotation;
    }
    set {
      base.Annotation = value;
      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) => {
          // Fill full circle with tricycle color
          BikeView.TricycleColor.SetFill();
          UIBezierPath.FromOval(new CGRect(0, 0, 40, 40)).Fill();
          // Fill pie with unicycle color
          BikeView.UnicycleColor.SetFill();
          var piePath = new UIBezierPath();
          piePath.AddArc(new CGPoint(20,20), 20, 0, (nfloat)(Math.PI * 2.0 * unicycleCount / count), true);
          piePath.AddLineTo(new CGPoint(20, 20));
          piePath.ClosePath();
          piePath.Fill();
          // Fill inner circle with white color
          UIColor.White.SetFill();
          UIBezierPath.FromOval(new CGRect(8, 8, 24, 24)).Fill();
          // Finally draw count text vertically and horizontally centered
          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);
        });
      }
    }
  }
  public ClusterView(){}
  public ClusterView(MKAnnotation annotation, string reuseIdentifier) : base(annotation, reuseIdentifier)
  {
    DisplayPriority = MKFeatureDisplayPriority.DefaultHigh;
    CollisionMode = MKAnnotationViewCollisionMode.Circle;
    // Offset center point to animate better with marker annotations
    CenterOffset = new CoreGraphics.CGPoint(0, -10);
  }
  private nuint CountBikeType(IMKAnnotation[] members, BikeType type) {
    nuint count = 0;
    foreach(Bike member in members){
      if (member.Type == type) ++count;
    }
    return count;
  }
}

4. Registrieren der Ansichtsklassen

Wenn das Kartenansicht-Steuerelement erstellt und einer Ansicht hinzugefügt wird, registrieren Sie die Anmerkungsansichtstypen, um das automatische Clusteringverhalten zu aktivieren, wenn die Karte verkleinert und verkleinert wird:

MapView.Register(typeof(BikeView), MKMapViewDefault.AnnotationViewReuseIdentifier);
MapView.Register(typeof(ClusterView), MKMapViewDefault.ClusterAnnotationViewReuseIdentifier);

5. Rendern Sie die Karte!

Wenn die Karte gerendert wird, werden Anmerkungsmarker gruppiert oder je nach Zoomfaktor gerendert. Wenn sich der Zoomfaktor ändert, animieren Marker in und aus Clustern.

Simulator mit gruppierten Markern auf der Karte

Weitere Informationen zum Anzeigen von Daten mit MapKit finden Sie im Abschnitt Karten .

Kompasstaste

iOS 11 bietet die Möglichkeit, den Kompass aus der Karte zu klappen und ihn an anderer Stelle in der Ansicht zu rendern. Ein Beispiel finden Sie in der Tandm-Beispiel-App .

Erstellen Sie eine Schaltfläche, die wie ein Kompass aussieht (einschließlich Liveanimation, wenn die Kartenausrichtung geändert wird), und rendert sie auf einem anderen Steuerelement.

Kompasstaste in der Navigationsleiste

Der folgende Code erstellt eine Kompassschaltfläche und rendert sie auf der Navigationsleiste:

var compass = MKCompassButton.FromMapView(MapView);
compass.CompassVisibility = MKFeatureVisibility.Visible;
NavigationItem.RightBarButtonItem = new UIBarButtonItem(compass);
MapView.ShowsCompass = false; // so we don't have two compasses!

Die ShowsCompass -Eigenschaft kann verwendet werden, um die Sichtbarkeit des Standardkompasses in der Kartenansicht zu steuern.

Skalierungsansicht

Fügen Sie die Skalierung an einer anderen Stelle in der Ansicht hinzu, indem Sie die MKScaleView.FromMapView() -Methode verwenden, um eine instance der Skalierungsansicht abzurufen, die an einer anderen Stelle in der Ansichtshierarchie hinzugefügt werden soll.

Auf einer Karte überlagerte Skalierungsansicht

var scale = MKScaleView.FromMapView(MapView);
scale.LegendAlignment = MKScaleViewAlignment.Trailing;
scale.TranslatesAutoresizingMaskIntoConstraints = false;
View.AddSubview(scale); // constraints omitted for simplicity
MapView.ShowsScale = false; // so we don't have two scale displays!

Die ShowsScale -Eigenschaft kann verwendet werden, um die Sichtbarkeit des Standardkompasses in der Kartenansicht zu steuern.

Schaltfläche "Benutzernachverfolgung"

Die Schaltfläche "Benutzernachverfolgung" zentriert die Karte auf den aktuellen Standort des Benutzers. Verwenden Sie die MKUserTrackingButton.FromMapView() -Methode, um eine instance der Schaltfläche abzurufen, Formatierungsänderungen anzuwenden und an einer anderen Stelle in der Ansichtshierarchie hinzuzufügen.

Schaltfläche

var button = MKUserTrackingButton.FromMapView(MapView);
button.Layer.BackgroundColor = UIColor.FromRGBA(255,255,255,80).CGColor;
button.Layer.BorderColor = UIColor.White.CGColor;
button.Layer.BorderWidth = 1;
button.Layer.CornerRadius = 5;
button.TranslatesAutoresizingMaskIntoConstraints = false;
View.AddSubview(button); // constraints omitted for simplicity