Nowe funkcje w zestawie MapKit w systemie iOS 11
System iOS 11 dodaje następujące nowe funkcje do zestawu MapKit:
Automatyczne grupowanie znaczników podczas powiększania
W przykładzie pokazano, jak zaimplementować nową funkcję klastrowania adnotacji systemu iOS 11.
1. Tworzenie podklasy MKPointAnnotation
Klasa adnotacji punktów reprezentuje każdy znacznik na mapie. Można je dodawać indywidualnie przy użyciu MapView.AddAnnotation()
tablicy lub z tablicy przy użyciu polecenia MapView.AddAnnotations()
.
Klasy adnotacji punktów nie mają reprezentacji wizualnej. Są one wymagane tylko do reprezentowania danych skojarzonych ze znacznikiem (co najważniejsze, Coordinate
właściwością, która jest jej szerokość geograficzna i długość geograficzna na mapie) oraz właściwościami niestandardowymi:
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. Tworzenie MKMarkerAnnotationView
podklasy dla pojedynczych znaczników
Widok adnotacji znacznika jest wizualną reprezentacją każdej adnotacji i jest stylizowany przy użyciu właściwości, takich jak:
- MarkerTintColor — kolor znacznika.
- GlyphText — tekst wyświetlany w znaczniku.
- GlyphImage — ustawia obraz wyświetlany w znaczniku.
- DisplayPriority — określa kolejność z (zachowanie stosu), gdy mapa jest zatłoczony znacznikami. Użyj jednej z wartości
Required
,DefaultHigh
lubDefaultLow
.
Aby obsługiwać automatyczne klastrowanie, należy również ustawić następujące ustawienia:
- ClusteringIdentifier — to kontrolki, które znaczniki są klasterowane razem. Możesz użyć tego samego identyfikatora dla wszystkich znaczników lub użyć różnych identyfikatorów, aby kontrolować sposób ich grupowania.
[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. Tworzenie obiektu MKAnnotationView
do reprezentowania klastrów znaczników
Chociaż widok adnotacji reprezentujący klaster znaczników może być prostym obrazem, użytkownicy oczekują, że aplikacja będzie dostarczać wizualne wskazówki dotyczące liczby znaczników zgrupowanych razem.
W przykładzie użyto funkcji CoreGraphics do renderowania liczby znaczników w klastrze, a także do reprezentowania wykresu okręgowego proporcji każdego typu znacznika.
Należy również ustawić:
- DisplayPriority — określa kolejność z (zachowanie stosu), gdy mapa jest zatłoczony znacznikami. Użyj jednej z wartości
Required
,DefaultHigh
lubDefaultLow
. - CollisionMode —
Circle
lubRectangle
.
[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. Rejestrowanie klas widoków
Gdy kontrolka widoku mapy jest tworzona i dodawana do widoku, zarejestruj typy widoków adnotacji, aby umożliwić automatyczne działanie klastrowania w miarę powiększenia i powiększenia mapy:
MapView.Register(typeof(BikeView), MKMapViewDefault.AnnotationViewReuseIdentifier);
MapView.Register(typeof(ClusterView), MKMapViewDefault.ClusterAnnotationViewReuseIdentifier);
5. Renderuj mapę!
Po renderowaniu mapy znaczniki adnotacji będą klastrowane lub renderowane w zależności od poziomu powiększenia. Wraz ze zmianą poziomu powiększenia znaczniki animują się w klastrach i poza nie.
Aby uzyskać więcej informacji na temat wyświetlania danych za pomocą zestawu MapKit, zapoznaj się z sekcją Mapy.
Przycisk Kompas
System iOS 11 dodaje możliwość wyskakowania kompasu z mapy i renderowania go w innym miejscu w widoku.
Utwórz przycisk, który wygląda jak kompas (w tym animacja na żywo po zmianie orientacji mapy) i renderuje go na innej kontrolce.
Poniższy kod tworzy przycisk kompasu i renderuje go na pasku nawigacyjnym:
var compass = MKCompassButton.FromMapView(MapView);
compass.CompassVisibility = MKFeatureVisibility.Visible;
NavigationItem.RightBarButtonItem = new UIBarButtonItem(compass);
MapView.ShowsCompass = false; // so we don't have two compasses!
Właściwość ShowsCompass
może służyć do kontrolowania widoczności domyślnego kompasu w widoku mapy.
Widok skalowania
Dodaj skalę w innym miejscu w widoku przy użyciu MKScaleView.FromMapView()
metody , aby uzyskać wystąpienie widoku skalowania, aby dodać inne miejsce w hierarchii widoków.
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!
Właściwość ShowsScale
może służyć do kontrolowania widoczności domyślnego kompasu w widoku mapy.
Przycisk śledzenia użytkowników
Przycisk śledzenia użytkownika wyśrodkuje mapę w bieżącej lokalizacji użytkownika. MKUserTrackingButton.FromMapView()
Użyj metody , aby uzyskać wystąpienie przycisku, zastosować zmiany formatowania i dodać inne miejsce w hierarchii widoków.
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