Neue Features in MapKit unter iOS 11
iOS 11 fügt mapKit die folgenden neuen Features hinzu:
Automatisches Gruppieren von Markierungen beim Zoomen
Das Beispiel zeigt, wie das neue iOS 11-Anmerkungsclustering-Feature implementiert wird.
1. Erstellen einer MKPointAnnotation
Unterklasse
Die Punktanmerkungsklasse stellt jede Markierung auf der Karte dar. Sie können einzeln mithilfe MapView.AddAnnotation()
oder aus einem Array hinzugefügt MapView.AddAnnotations()
werden.
Punktanmerkungsklassen verfügen nicht über eine visuelle Darstellung, sie sind nur erforderlich, um die mit der Markierung verknüpften Daten darzustellen (vor allem die Eigenschaft, die Coordinate
breiten- und längengrad auf der Karte ist) 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 Markierungen
Die Markierungsanmerkungsansicht ist die visuelle Darstellung jeder Anmerkung und wird mithilfe von Eigenschaften wie:
- MarkerTintColor – Die Farbe für die Markierung.
- GlyphText – Text, der in der Markierung angezeigt wird.
- GlyphImage – Legt das Bild fest, das in der Markierung angezeigt wird.
- DisplayPriority – Bestimmt die Z-Reihenfolge (Stapelverhalten), wenn die Karte mit Markierungen überfüllt ist. Verwenden Sie einen von
Required
, ,DefaultHigh
oderDefaultLow
.
Um die automatische Clustering zu unterstützen, müssen Sie auch Folgendes festlegen:
- ClusteringIdentifier – Dies steuert, welche Markierungen gruppiert werden. Sie können denselben Bezeichner für alle Ihre Markierungen 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 sie eine MKAnnotationView
, die Cluster von Markern darstellt
Während die Anmerkungsansicht, die einen Cluster von Markierungen darstellt, ein einfaches Bild sein könnte , erwarten Die Benutzer, dass die App visuelle Hinweise dazu liefert, wie viele Markierungen gruppiert wurden.
Im Beispiel wird CoreGraphics verwendet, um die Anzahl der Markierungen im Cluster sowie eine Kreisdiagrammdarstellung des Proportionen jedes Markertyps zu rendern.
Sie sollten auch Folgendes festlegen:
- DisplayPriority – Bestimmt die Z-Reihenfolge (Stapelverhalten), wenn die Karte mit Markierungen überfüllt ist. Verwenden Sie einen von
Required
, ,DefaultHigh
oderDefaultLow
. - CollisionMode –
Circle
oderRectangle
.
[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 Kartenansichtssteuerelement erstellt und einer Ansicht hinzugefügt wird, registrieren Sie die Anmerkungsansichtstypen, um das automatische Clusteringverhalten zu aktivieren, wenn die Karte vergrößert 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 Anmerkungenmarkierungen gruppiert oder gerendert, je nach Zoomfaktor. Wenn sich der Zoomfaktor ändert, werden Markierungen in und außerhalb von Clustern animiert.
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 herauszufüllen und an anderer Stelle in der Ansicht zu rendern.
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.
Der folgende Code erstellt eine Kompasstaste 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 Standardkompasss innerhalb der Kartenansicht zu steuern.
Skalierungsansicht
Fügen Sie die Skalierung an anderer Stelle in der Ansicht mithilfe der MKScaleView.FromMapView()
Methode hinzu, um eine Instanz der Skalierungsansicht abzurufen, die an anderer Stelle in der Ansichtshierarchie hinzugefügt werden soll.
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 Standardkompasss innerhalb der Kartenansicht zu steuern.
Schaltfläche "Benutzerverfolgung"
Die Schaltfläche "Benutzerverfolgung" zentrieren die Karte auf der aktuellen Position des Benutzers. Verwenden Sie die MKUserTrackingButton.FromMapView()
Methode, um eine Instanz der Schaltfläche abzurufen, Formatierungsänderungen anzuwenden und an anderer Stelle in der Ansichtshierarchie hinzuzufügen.
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