Nové funkce v MapKitu v iOSu 11

iOS 11 přidá do MapKitu následující nové funkce:

Map showing clustered markers and compass button

Automatické seskupení značek při přiblížení

Ukázka MapKitu "Tandm" ukazuje, jak implementovat novou funkci clusteringu poznámek pro iOS 11.

1. Vytvoření MKPointAnnotation podtřídy

Třída poznámky k bodu představuje každou značku na mapě. Lze je přidat jednotlivě pomocí MapView.AddAnnotation() pole nebo z pole pomocí MapView.AddAnnotations().

Třídy bodových poznámek nemají vizuální reprezentaci, jsou vyžadovány pouze k reprezentaci dat přidružených ke značce (nejdůležitější je vlastnost, Coordinate která je jeho zeměpisná šířka a délka na mapě) a všechny vlastní vlastnosti:

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. Vytvoření MKMarkerAnnotationView podtřídy pro jednotlivé značky

Zobrazení poznámek značky je vizuální reprezentace každé poznámky a je stylována pomocí vlastností, jako jsou:

  • MarkerTintColor – barva značky.
  • GlyphText – Text zobrazený ve značce.
  • GlyphImage – Nastaví obrázek, který se zobrazí ve značce.
  • DisplayPriority – Určuje pořadí vykreslování (chování při vytváření zásobníků), když je mapa přeplněna značkami. Použijte jeden z Required, DefaultHighnebo DefaultLow.

Pokud chcete podporovat automatické clusteringy, musíte také nastavit:

  • ClusteringIdentifier – určuje, které značky se seskupí dohromady. Stejný identifikátor můžete použít pro všechny značky nebo můžete použít různé identifikátory k řízení jejich seskupení.
[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. Vytvořte skupinu MKAnnotationView představující shluky značek.

I když zobrazení poznámek, které představuje cluster značek , může být jednoduchým obrázkem, uživatelé očekávají, že aplikace poskytne vizuální pomůcky o tom, kolik značek bylo seskupených dohromady.

Vzorový kód používá CoreGraphics k vykreslení počtu značek v clusteru a také znázornění podílu jednotlivých typů značek v kruhovém grafu.

Měli byste také nastavit:

  • DisplayPriority – Určuje pořadí vykreslování (chování při vytváření zásobníků), když je mapa přeplněna značkami. Použijte jeden z Required, DefaultHighnebo DefaultLow.
  • KolizeModeCircle nebo 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. Registrace tříd zobrazení

Při vytváření a přidávání ovládacího prvku zobrazení mapy zaregistrujte typy zobrazení poznámek a povolte automatické chování clusteringu při přiblížení a oddálení mapy:

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

5. Vykreslení mapy!

Při vykreslení mapy se značky poznámek seskupí nebo vykreslí v závislosti na úrovni přiblížení. Když se úroveň přiblížení změní, značky se animují do a z clusterů.

Simulator showing clustered markers on map

Další informace o zobrazení dat pomocí MapKitu najdete v Mapy části.

Tlačítko kompasu

iOS 11 přidá možnost zobrazit kompas z mapy a vykreslit ho jinde v zobrazení. Příklad najdete v ukázkové aplikaci Tandm.

Vytvořte tlačítko, které vypadá jako kompas (včetně živé animace při změně orientace mapy) a vykresluje ho na jiném ovládacím prvku.

Compass button in navigation bar

Následující kód vytvoří tlačítko kompasu a vykreslí ho na navigačním panelu:

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

Vlastnost ShowsCompass lze použít k řízení viditelnosti výchozího kompasu uvnitř zobrazení mapy.

Zobrazení měřítka

Přidejte měřítko jinde v zobrazení pomocí MKScaleView.FromMapView() metody, abyste získali instanci zobrazení škálování pro přidání jinde v hierarchii zobrazení.

Scale view overlaid on a map

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!

Vlastnost ShowsScale lze použít k řízení viditelnosti výchozího kompasu uvnitř zobrazení mapy.

Tlačítko Sledování uživatelů

Tlačítko sledování uživatele zacentruje mapu na aktuální umístění uživatele. MKUserTrackingButton.FromMapView() Pomocí metody můžete získat instanci tlačítka, použít změny formátování a přidat jinam v hierarchii zobrazení.

User location button overlaid on a map

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