Novos recursos do MapKit no iOS 11
O iOS 11 adiciona os seguintes novos recursos ao MapKit:
Agrupar marcadores automaticamente durante o zoom
O exemplo mostra como implementar o novo recurso de clustering de anotações do iOS 11.
1. Criar uma MKPointAnnotation
subclasse
A classe de anotação de ponto representa cada marcador no mapa. Eles podem ser adicionados individualmente usando MapView.AddAnnotation()
ou a partir de uma matriz usando MapView.AddAnnotations()
o .
As classes de anotação de ponto não têm uma representação visual, elas são necessárias apenas para representar os dados associados ao marcador (o mais importante, a Coordinate
propriedade que é sua latitude e longitude no mapa) e quaisquer propriedades personalizadas:
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. Criar uma MKMarkerAnnotationView
subclasse para marcadores únicos
O modo de exibição de anotação de marcador é a representação visual de cada anotação e é estilizado usando propriedades como:
- MarkerTintColor – A cor do marcador.
- GlyphText – Texto exibido no marcador.
- GlyphImage – Define a imagem que é exibida no marcador.
- DisplayPriority – Determina a ordem z (comportamento de empilhamento) quando o mapa está repleto de marcadores. Use um dos
Required
,DefaultHigh
ouDefaultLow
.
Para oferecer suporte ao clustering automático, você também deve definir:
- ClusteringIdentifier – Controla quais marcadores são agrupados. Você pode usar o mesmo identificador para todos os marcadores ou usar identificadores diferentes para controlar a maneira como eles são agrupados.
[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. Crie um MKAnnotationView
para representar clusters de marcadores
Embora o modo de exibição de anotação que representa um cluster de marcadores possa ser uma imagem simples, os usuários esperam que o aplicativo forneça pistas visuais sobre quantos marcadores foram agrupados.
O exemplo usa CoreGraphics para renderizar o número de marcadores no cluster, bem como uma representação de gráfico circular da proporção de cada tipo de marcador.
Você também deve definir:
- DisplayPriority – Determina a ordem z (comportamento de empilhamento) quando o mapa está repleto de marcadores. Use um dos
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. Registre as classes de exibição
Quando o controle de exibição de mapa estiver sendo criado e adicionado a uma exibição, registre os tipos de exibição de anotação para habilitar o comportamento de clustering automático à medida que o mapa é ampliado e reduzido:
MapView.Register(typeof(BikeView), MKMapViewDefault.AnnotationViewReuseIdentifier);
MapView.Register(typeof(ClusterView), MKMapViewDefault.ClusterAnnotationViewReuseIdentifier);
5. Renderize o mapa!
Quando o mapa é renderizado, os marcadores de anotação serão agrupados ou renderizados, dependendo do nível de zoom. À medida que o nível de zoom muda, os marcadores são animados dentro e fora dos clusters.
Consulte a seção Mapas para obter mais informações sobre como exibir dados com o MapKit.
Botão da Bússola
O iOS 11 adiciona a capacidade de tirar a bússola do mapa e renderizá-la em outro lugar da visualização.
Crie um botão que se pareça com uma bússola (incluindo animação ao vivo quando a orientação do mapa for alterada) e renderize-o em outro controle.
O código abaixo cria um botão de bússola e o renderiza na barra de navegação:
var compass = MKCompassButton.FromMapView(MapView);
compass.CompassVisibility = MKFeatureVisibility.Visible;
NavigationItem.RightBarButtonItem = new UIBarButtonItem(compass);
MapView.ShowsCompass = false; // so we don't have two compasses!
A ShowsCompass
propriedade pode ser usada para controlar a visibilidade da bússola padrão dentro da visualização de mapa.
Visualização de escala
Adicione a escala em outro lugar no modo de exibição usando o MKScaleView.FromMapView()
método para obter uma instância do modo de exibição de escala para adicionar em outro lugar na hierarquia do modo de exibição.
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!
A ShowsScale
propriedade pode ser usada para controlar a visibilidade da bússola padrão dentro da visualização de mapa.
Botão de Rastreamento de Usuário
O botão de rastreamento do usuário centraliza o mapa na localização atual do usuário. Use o MKUserTrackingButton.FromMapView()
método para obter uma instância do botão, aplicar alterações de formatação e adicionar em outro lugar na hierarquia de exibição.
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