Partager via


Nouvelles fonctionnalités de MapKit sur iOS 11

iOS 11 ajoute les nouvelles fonctionnalités suivantes à MapKit :

Carte montrant les marqueurs en cluster et le bouton boussole

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, DefaultHighou DefaultLow.

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, DefaultHighou DefaultLow.
  • CollisionModeCircle ou 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. 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.

Simulateur montrant les marqueurs en cluster sur la carte

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.

Bouton Boussole dans la barre de navigation

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.

Mise à l’échelle de la vue superposée sur une carte

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.

Bouton Emplacement de l’utilisateur superposé sur une carte

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