Nouvelles fonctionnalités de MapKit sur iOS 11
iOS 11 ajoute les nouvelles fonctionnalités suivantes à MapKit :
Regroupement automatique des marqueurs lors du zoom
L’exemple montre comment implémenter la nouvelle fonctionnalité de clustering d’annotations iOS 11.
1. Créer une MKPointAnnotation
sous-classe
La classe d’annotation de point représente chaque marqueur sur la carte. Ils peuvent être ajoutés individuellement à l’aide MapView.AddAnnotation()
ou à partir d’un tableau à l’aide MapView.AddAnnotations()
de .
Les classes d’annotation de point n’ont pas de représentation visuelle, elles sont uniquement requises pour représenter les données associées au marqueur (la Coordinate
propriété qui est sa latitude et sa longitude sur la carte) et toutes les propriétés personnalisées :
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. Créer une MKMarkerAnnotationView
sous-classe pour les marqueurs uniques
La vue d’annotation de marqueur est la représentation visuelle de chaque annotation et est styleée à l’aide de propriétés telles que :
- MarkerTintColor : couleur du marqueur.
- GlyphText : texte affiché dans le marqueur.
- GlyphImage : définit l’image affichée dans le marqueur.
- DisplayPriority : détermine l’ordre z (comportement d’empilement) lorsque la carte est encombrée de marqueurs. Utilisez l’un des
Required
,DefaultHigh
ouDefaultLow
.
Pour prendre en charge le clustering automatique, vous devez également définir :
- ClusteringIdentifier : contrôle les marqueurs qui sont regroupés. Vous pouvez utiliser le même identificateur pour tous vos marqueurs, ou utiliser différents identificateurs pour contrôler la façon dont ils sont regroupés.
[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. Créer un MKAnnotationView
pour représenter des clusters de marqueurs
Bien que la vue d’annotation qui représente un cluster de marqueurs puisse être une image simple, les utilisateurs s’attendent à ce que l’application fournisse des indications visuelles sur le nombre de marqueurs qui ont été regroupés.
L’exemple utilise CoreGraphics pour afficher le nombre de marqueurs dans le cluster, ainsi qu’une représentation de graphique en cercle de la proportion de chaque type de marqueur.
Vous devez également définir :
- DisplayPriority : détermine l’ordre z (comportement d’empilement) lorsque la carte est encombrée de marqueurs. Utilisez l’un des
Required
,DefaultHigh
ouDefaultLow
. - CollisionMode –
Circle
ouRectangle
.
[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. Inscrire les classes d’affichage
Lorsque le contrôle d’affichage de carte est créé et ajouté à une vue, inscrivez les types d’affichage d’annotation pour activer le comportement de clustering automatique, car la carte est zoomée et arrière :
MapView.Register(typeof(BikeView), MKMapViewDefault.AnnotationViewReuseIdentifier);
MapView.Register(typeof(ClusterView), MKMapViewDefault.ClusterAnnotationViewReuseIdentifier);
5. Affichez la carte !
Lorsque la carte est rendue, les marqueurs d’annotation sont regroupés ou rendus en fonction du niveau de zoom. À mesure que le niveau de zoom change, les marqueurs s’animent dans et hors des clusters.
Pour plus d’informations sur l’affichage des données avec MapKit, consultez la section Cartes.
Bouton Boussole
iOS 11 ajoute la possibilité de faire sortir la boussole de la carte et de la rendre ailleurs dans la vue.
Créez un bouton qui ressemble à une boussole (y compris l’animation dynamique lorsque l’orientation de la carte est modifiée) et le restitue sur un autre contrôle.
Le code ci-dessous crée un bouton boussole et le affiche dans la barre de navigation :
var compass = MKCompassButton.FromMapView(MapView);
compass.CompassVisibility = MKFeatureVisibility.Visible;
NavigationItem.RightBarButtonItem = new UIBarButtonItem(compass);
MapView.ShowsCompass = false; // so we don't have two compasses!
La ShowsCompass
propriété peut être utilisée pour contrôler la visibilité de la boussole par défaut à l’intérieur de la vue cartographique.
Mode Mise à l’échelle
Ajoutez l’échelle ailleurs dans la vue à l’aide de la MKScaleView.FromMapView()
méthode pour obtenir une instance de la vue d’échelle à ajouter ailleurs dans la hiérarchie d’affichage.
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!
La ShowsScale
propriété peut être utilisée pour contrôler la visibilité de la boussole par défaut à l’intérieur de la vue cartographique.
Bouton Suivi des utilisateurs
Le bouton suivi de l’utilisateur centre la carte sur l’emplacement actuel de l’utilisateur. Utilisez la MKUserTrackingButton.FromMapView()
méthode pour obtenir une instance du bouton, appliquer des modifications de mise en forme et ajouter ailleurs dans la hiérarchie d’affichage.
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