Marcadores de mapa de Xamarin.Forms
El control Xamarin.FormsMap
permite marcar ubicaciones con objetos Pin
. Pin
es un marcador de mapa que abre una ventana de información cuando se pulsa:
Cuando se agrega un objeto Pin
a la colección Map.Pins
, la marca o pin se representa en el mapa.
La clase Pin
tiene las siguientes propiedades:
Address
, de tipostring
, que normalmente representa la dirección de la ubicación de la marca o pin. Sin embargo, puede ser cualquier contenidostring
, no solo una dirección.Label
, de tipostring
, que normalmente representa el título del pin o marca.Position
, de tipoPosition
, que representa la latitud y la longitud del pin o marca.Type
, de tipoPinType
, que representa el tipo de pin o marca.
Las propiedades están respaldadas por objetos BindableProperty
, lo que significa que un objeto Pin
puede ser destino de los enlaces de datos. Para más información sobre los objetos de enlace de datos Pin
, consulta Presentación de una colección de pines.
Además, la clase Pin
define los eventos MarkerClicked
y InfoWindowClicked
. El evento MarkerClicked
se desencadena cuando se pulsa en una marca y el evento InfoWindowClicked
se desencadena cuando se pulsa la ventana de información. El objeto PinClickedEventArgs
que acompaña a ambos eventos tiene una propiedad HideInfoWindow
, de tipo bool
.
Mostrar un pin
Un Pin
se puede agregar a Map
en XAML:
<ContentPage ...
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps">
<maps:Map x:Name="map"
IsShowingUser="True"
MoveToLastRegionOnLayoutChange="False">
<x:Arguments>
<maps:MapSpan>
<x:Arguments>
<maps:Position>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</maps:Position>
<x:Double>0.01</x:Double>
<x:Double>0.01</x:Double>
</x:Arguments>
</maps:MapSpan>
</x:Arguments>
<maps:Map.Pins>
<maps:Pin Label="Santa Cruz"
Address="The city with a boardwalk"
Type="Place">
<maps:Pin.Position>
<maps:Position>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</maps:Position>
</maps:Pin.Position>
</maps:Pin>
</maps:Map.Pins>
</maps:Map>
</ContentPage>
Este XAML crea un objeto Map
con el que muestra la región especificada por el objeto MapSpan
. El objeto MapSpan
se centra en la latitud y la longitud representadas por un objeto Position
, que se extiende 0,01 grados de latitud y longitud. Se agrega un objeto Pin
a la colección Map.Pins
y se dibuja en Map
en la ubicación especificada por su propiedad Position
. Para obtener información sobre la estructura Position
, vea Posición y distancia de mapa. Para obtener información sobre cómo pasar argumentos en XAML a objetos que carecen de constructores predeterminados,vea Transferencia de argumentos en XAML.
El código de C# equivalente es el siguiente:
using Xamarin.Forms.Maps;
// ...
Map map = new Map
{
// ...
};
Pin pin = new Pin
{
Label = "Santa Cruz",
Address = "The city with a boardwalk",
Type = PinType.Place,
Position = new Position(36.9628066, -122.0194722)
};
map.Pins.Add(pin);
Advertencia
Si no se establece la propiedad Pin.Label
, se iniciará una excepción ArgumentException
cuando se agregue Pin
a Map
.
Como resultado de este código de ejemplo, solo se representa un único pin o marca en un mapa:
Interacción con un pin
De forma predeterminada, cuando se pulsa en un Pin
, aparece la ventana de información:
Al pulsar en otro lugar del mapa, se cierra la ventana de información.
La clase Pin
define un evento MarkerClicked
, que se desencadena cuando se pulsa en un Pin
. No es necesario controlar este evento para mostrar la ventana de información. En su lugar, este evento debe usarse cuando hay un requisito para recibir una notificación de que se ha pulsado un pin específico.
La clase Pin
también define un evento InfoWindowClicked
que se desencadena cuando se pulsa en una ventana de información. Este evento debe usarse cuando se necesita recibir una notificación de que se ha pulsado en una ventana de información específica.
El siguiente código muestra un ejemplo de cómo se gestionan estos eventos:
using Xamarin.Forms.Maps;
// ...
Pin boardwalkPin = new Pin
{
Position = new Position(36.9641949, -122.0177232),
Label = "Boardwalk",
Address = "Santa Cruz",
Type = PinType.Place
};
boardwalkPin.MarkerClicked += async (s, args) =>
{
args.HideInfoWindow = true;
string pinName = ((Pin)s).Label;
await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok");
};
Pin wharfPin = new Pin
{
Position = new Position(36.9571571, -122.0173544),
Label = "Wharf",
Address = "Santa Cruz",
Type = PinType.Place
};
wharfPin.InfoWindowClicked += async (s, args) =>
{
string pinName = ((Pin)s).Label;
await DisplayAlert("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok");
};
El objeto PinClickedEventArgs
que acompaña a ambos eventos tiene una propiedad HideInfoWindow
, de tipo bool
. Cuando esta propiedad se establece en true
dentro de un controlador de eventos, la ventana de información se ocultará.
Tipos de pines
Los objetos Pin
incluyen una propiedad Type
, de tipo PinType
, que representa el tipo de pin o marca. La enumeración PinType
define los miembros siguientes:
Generic
representa un pin genérico.Place
, representa un pin o marca de un lugar.SavedPin
, representa un pin o marca de una ubicación guardada.SearchResult
, representa un pin o marca de un resultado de búsqueda.
Aunque establecer la propiedad Pin.Type
en cualquier miembro PinType
no cambia la apariencia de la marca o pin representado. En su lugar, debe crear un representador personalizado para personalizar la apariencia del marcador. Para más información, vea Personalización de un marcador de mapa.
Presentación de una colección de pin
La clase Map
define las propiedades siguientes:
ItemsSource
, de tipoIEnumerable
, que colección de elementosIEnumerable
que se van a mostrar.ItemTemplate
, de tipoDataTemplate
, que especifica el elementoDataTemplate
se va a aplicar a cada elemento de la colección de elementos mostrados.ItemTemplateSelector
, de tipoDataTemplateSelector
, que especifica el elementoDataTemplateSelector
que se usará para elegir una instancia deDataTemplate
para un elemento en tiempo de ejecución.
Importante
Si estableces las propiedades ItemTemplate
y ItemTemplateSelector
, la prioridad la tiene la propiedad ItemTemplate
.
Map
se puede rellenar con marcadores mediante el enlace de datos para enlazar su propiedad ItemsSource
a una colección IEnumerable
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
x:Class="WorkingWithMaps.PinItemsSourcePage">
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Locations}">
<maps:Map.ItemTemplate>
<DataTemplate>
<maps:Pin Position="{Binding Position}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</maps:Map.ItemTemplate>
</maps:Map>
...
</Grid>
</ContentPage>
Los datos de propiedad ItemsSource
se enlazan a la propiedad Locations
del modelo de vista conectado, que devuelve ObservableCollection
de objetos Location
, que es un tipo personalizado. Cada objeto Location
define las propiedades Address
y Description
, de tipo string
, y una propiedad Position
, de tipo Position
.
La apariencia de cada elemento de la colección IEnumerable
se define estableciendo la propiedad ItemTemplate
en DataTemplate
que contiene un objeto Pin
que los datos enlazan a las propiedades adecuadas.
En las capturas de pantalla siguientes se muestra un elemento Map
que muestra una colección de Pin
mediante el enlace de datos:
Elección de la apariencia del elemento en tiempo de ejecución
La apariencia de cada elemento de la colección IEnumerable
se puede elegir en tiempo de ejecución, en función del valor del elemento, estableciendo la propiedad ItemTemplateSelector
en DataTemplateSelector
:
<ContentPage ...
xmlns:local="clr-namespace:WorkingWithMaps"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps">
<ContentPage.Resources>
<local:MapItemTemplateSelector x:Key="MapItemTemplateSelector">
<local:MapItemTemplateSelector.DefaultTemplate>
<DataTemplate>
<maps:Pin Position="{Binding Position}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</local:MapItemTemplateSelector.DefaultTemplate>
<local:MapItemTemplateSelector.XamarinTemplate>
<DataTemplate>
<!-- Change the property values, or the properties that are bound to. -->
<maps:Pin Position="{Binding Position}"
Address="{Binding Address}"
Label="Xamarin!" />
</DataTemplate>
</local:MapItemTemplateSelector.XamarinTemplate>
</local:MapItemTemplateSelector>
</ContentPage.Resources>
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Locations}"
ItemTemplateSelector="{StaticResource MapItemTemplateSelector}" />
...
</Grid>
</ContentPage>
En el ejemplo siguiente se muestra la clase MapItemTemplateSelector
:
public class MapItemTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate XamarinTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((Location)item).Address.Contains("San Francisco") ? XamarinTemplate : DefaultTemplate;
}
}
La clase MapItemTemplateSelector
define propiedades DataTemplate
DefaultTemplate
y XamarinTemplate
que se establecen en diferentes plantillas de datos. El método OnSelectTemplate
devuelve XamarinTemplate
, que muestra “Xamarin” como una etiqueta cuando se pulsa Pin
, cuando el elemento tiene una dirección que contiene “San Francisco”. Cuando el elemento no tiene una dirección que contenga “San Francisco”, el método OnSelectTemplate
devuelve DefaultTemplate
.
Nota:
Un caso de uso de esta funcionalidad es enlazar propiedades de objetos Pin
de subclase a diferentes propiedades, en función del subtipo Pin
.
Para más información sobre los selectores de plantillas de datos, vea Creación de una instancia de Xamarin.Forms DataTemplateSelector.