Xamarin.Forms Pinos de mapa
O controle Xamarin.FormsMap
permite que os locais sejam marcados com objetos Pin
. Um Pin
é um marcador de mapa que abre uma janela de informações quando tocado:
Quando um objeto Pin
é adicionado à coleção Map.Pins
, o alfinete é renderizado no mapa.
A classe Pin
tem as propriedades a seguir:
Address
, do tipostring
, que normalmente representa o endereço da localização do alfinete. No entanto, isso pode ser qualquer conteúdostring
, não apenas um endereço.Label
, do tipostring
, que normalmente representa o título do alfinete.Position
, do tipoPosition
, que representa a latitude e longitude do alfinete.Type
, do tipoPinType
, que representa o tipo de alfinete.
Essas propriedades são apoiadas por objetos BindableProperty
, o que significa que um Pin
pode ser alvo de associações de dados. Para obter mais informações sobre objetos Pin
de vinculação de dados, consulte Exibir uma coleção de alfinetes.
Além disso, a classe Pin
define eventos MarkerClicked
e InfoWindowClicked
. O evento MarkerClicked
é disparado quando um alfinete é tocado e o evento InfoWindowClicked
é disparado quando a janela de informações é tocada. O objeto PinClickedEventArgs
que acompanha ambos os eventos tem apenas uma propriedade HideInfoWindow
, do tipo bool
.
Exibir um alfinete
Um Pin
pode ser adicionado a um Map
em 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>
Esse XAML cria um objeto Map
que mostra a região especificada pelo objeto MapSpan
. O objeto MapSpan
é centrado na latitude e longitude representadas por um objeto Position
, que se estende 0,01 graus de latitude e longitude. Um objeto Pin
é adicionado à coleção Map.Pins
e desenhado no Map
no local especificado pela propriedade Position
dele. Para obter informações sobre o Position
struct, consulte Mapear posição e distância. Para obter informações sobre como passar argumentos em XAML para objetos que não têm construtores padrão, consulte Passando argumentos em XAML.
Este é o código C# equivalente:
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);
Aviso
A falha ao definir a Pin.Label
propriedade resultará em um ArgumentException
lançamento quando o Pin
for adicionado a um Map
.
Este código de exemplo resulta em apenas um alfinete sendo renderizado em um mapa:
Interagir com um alfinete
Por padrão, quando um Pin
é tocado, a janela de informações dele é exibida:
Tocar em outro lugar no mapa fecha a janela de informações.
A classe Pin
define um evento MarkerClicked
, que é acionado quando um Pin
é tocado. Não é necessário manipular esse evento para exibir a janela de informações. Em vez disso, esse evento deverá ser manipulado quando houver um requisito para ser notificado de que um alfinete específico foi tocado.
A classe Pin
também define um evento InfoWindowClicked
que é acionado quando uma janela de informações é tocada. Esse evento deverá ser manipulado quando houver um requisito para ser notificado de que uma janela de informações específica foi tocada.
O seguinte código mostra um exemplo de manipulação desses 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");
};
O objeto PinClickedEventArgs
que acompanha ambos os eventos tem apenas uma propriedade HideInfoWindow
, do tipo bool
. Quando essa propriedade é definida como true
dentro de um manipulador de eventos, a janela de informações é ocultada.
Tipos de alfinete
Os objetos Pin
incluem uma propriedade Type
, do tipo PinType
, que representa o tipo de alfinete. A enumeração PinType
define os seguintes membros:
Generic
, que representa um alfinete genérico.Place
, que representa um alfinete para um lugar.SavedPin
, que representa um alfinete para um local salvo.SearchResult
, que representa um alfinete para um resultado de pesquisa.
No entanto, definir a propriedade Pin.Type
como qualquer membro PinType
não altera a aparência do alfinete renderizado. Em vez disso, você deve criar um renderizador personalizado para personalizar a aparência do pino. Para obter mais informações, consulte Personalizando um alfinete de mapa.
Exibir uma coleção de marcadores
A classe Map
define as seguintes propriedades:
ItemsSource
, do tipoIEnumerable
, que especifica a coleção deIEnumerable
itens a serem exibidos.ItemTemplate
, do tipoDataTemplate
, que especifica oDataTemplate
a ser aplicado a cada item na coleção de itens exibidos.ItemTemplateSelector
, do tipoDataTemplateSelector
, que especifica oDataTemplateSelector
que será usado para escolher umDataTemplate
para um item em tempo de execução.
Importante
A propriedade ItemTemplate
tem precedência quando as propriedades ItemTemplate
e ItemTemplateSelector
estão definidas.
Um Map
pode ser preenchido com alfinetes usando a associação de dados para associar sua propriedade ItemsSource
a uma coleção 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>
Os dados da propriedade ItemsSource
se vinculam à propriedade Locations
do modelo de exibição conectado, que retorna um ObservableCollection
de objetos Location
, que é um tipo personalizado. Cada objeto Location
define propriedades Address
e Description
, do tipo string
, e uma propriedade Position
, do tipo Position
.
A aparência de cada item na coleção IEnumerable
é definida configurando-se a propriedade ItemTemplate
como um DataTemplate
que contém um objeto Pin
, cujos dados são associados às propriedades adequadas.
As capturas de tela a seguir mostram a exibição de Map
uma Pin
coleção usando a associação de dados:
Escolher a aparência do item em tempo de execução
A aparência de cada item na coleção IEnumerable
pode ser escolhida em tempo de execução, com base no valor do item, definindo a propriedade ItemTemplateSelector
como 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>
O exemplo a seguir mostra a classe 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;
}
}
A MapItemTemplateSelector
classe define propriedades DefaultTemplate
e XamarinTemplate
DataTemplate
que são configuradas para diferentes modelos de dados. O método OnSelectTemplate
retorna o XamarinTemplate
, que exibe "Xamarin" como um rótulo quando um Pin
é tocado, quando o item tem um endereço que contém "San Francisco". Quando o item não tem um endereço que contém "São Francisco", o método OnSelectTemplate
retorna o DefaultTemplate
.
Observação
Um caso de uso para essa funcionalidade é associar propriedades de objetos de Pin
subclasse a propriedades diferentes, com base no Pin
subtipo.
Para obter mais informações sobre seletores de modelo de dados, consulte Criando um Xamarin.Forms DataTemplateSelector.