Asignar
El control .NET Multi-platform App UI (.NET MAUI) Map es una vista multiplataforma para mostrar y anotar mapas. El control Map usa el control de mapa nativo en cada plataforma y lo proporciona el paquete Microsoft.Maui.Controls.Maps NuGet.
Importante
El control Map no se admite en Windows debido a la falta de un control de mapa en WinUI. Pero el paquete CommunityToolkit.Maui.Maps NuGet proporciona acceso a mapas de Bing a través de WebView
en Windows. Para más información, consulte Introducción.
Configurar
El control Map usa el control de mapa nativo en cada plataforma. Esto proporciona una experiencia de mapas rápida y familiar para los usuarios, pero significa que se necesitan algunos pasos de configuración para cumplir los requisitos de API de cada plataforma.
Inicialización de mapa
El control Map lo proporciona el paquete Microsoft.Maui.Controls.Maps NuGet, que se debe agregar al proyecto de aplicación .NET MAU.
Después de instalar el paquete NuGet, debe inicializarse en la aplicación llamando al método UseMauiMap
en el objeto MauiAppBuilder
del método MauiProgram
de tu clase CreateMauiApp
:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
.UseMauiMaps();
return builder.Build();
}
}
Una vez agregado e inicializado el paquete NuGet, las API de Map se pueden usar en el proyecto.
Configuración de la plataforma
Se requiere configuración adicional en Android antes de que se muestre el mapa. Además, en iOS, Android y Mac Catalyst, el acceso a la ubicación del usuario requiere que se hayan concedido permisos de ubicación a la aplicación.
iOS y Mac Catalyst
Mostrar e interactuar con un mapa en iOS y Mac Catalyst no requiere ninguna configuración adicional. Pero para acceder a los servicios de ubicación, debe establecer las solicitudes de servicios de ubicación necesarias en Info.plist. Normalmente, estos serán uno o varios de los siguientes:
NSLocationAlwaysAndWhenInUseUsageDescription
: para usar los servicios de ubicación en todo momento.NSLocationWhenInUseUsageDescription
: para usar los servicios de ubicación cuando la aplicación está en uso.
Para obtener más información, consulta Elección de la autorización de servicios de ubicación para solicitar en developer.apple.com.
La representación de XML de estas claves en Info.plist se muestra a continuación: Debe actualizar los valores string
para reflejar cómo usa la aplicación la información de ubicación:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Can we use your location at all times?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Can we use your location when your app is being used?</string>
Luego, cuando la aplicación intenta acceder a la ubicación del usuario, se muestra un mensaje solicitando acceso:
Android
El proceso de configuración para mostrar e interactuar con un mapa en Android es:
- Obtén una clave de API de Google Maps y agrégala al manifiesto de la aplicación.
- Especifica el número de versión de Google Play Services en el manifiesto.
- [opcional] Especifica los permisos de ubicación en el manifiesto.
- [opcional] Especifica el permiso WRITE_EXTERNAL_STORAGE en el manifiesto.
Obtener una clave de API de Google Maps
Para usar el control Map en Android, debes generar una clave de API, que usará google Google Maps SDK en el que el control Map se basa en Android. Para ello, sigue las instrucciones de Configuración en Google Cloud Console y Uso de claves de API en developers.google.com.
Una vez que hayas obtenido una clave de API, debe agregarse dentro del elemento <application>
de tu archivo Platforms/Android/AndroidManifest.xml, especificándolo como el valor de los metadatos com.google.android.geo.API_KEY
:
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
<meta-data android:name="com.google.android.geo.API_KEY" android:value="PASTE-YOUR-API-KEY-HERE" />
</application>
Esto inserta la clave de API en el manifiesto. Sin una clave de API válida, el control Map mostrará una cuadrícula en blanco.
Nota:
com.google.android.geo.API_KEY
es el nombre de metadatos recomendado para la clave de API. Se puede usar una clave con este nombre para autenticarse en varias API basadas en Google Maps en Android. Para la compatibilidad con versiones anteriores, se puede usar el nombre de los metadatos com.google.android.maps.v2.API_KEY
, pero solo permite la autenticación en Android Maps API v2. Una aplicación solo puede especificar uno de los nombres de metadatos de clave de API.
Especificar el número de versión de Google Play Services
Agrega la siguiente declaración en el elemento <application>
de AndroidManifest.xml:
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
Esto incorpora al manifiesto la versión de Google Play Services con la que se compiló la aplicación.
Especificar permisos de ubicación
Si la aplicación necesita acceder a la ubicación del usuario, debes solicitar permiso agregando al manifiesto el permiso ACCESS_COARSE_LOCATION
o ACCESS_FINE_LOCATION
(o ambos) como elemento secundario del elemento <manifest>
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<!-- Required to access the user's location -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
El permiso ACCESS_COARSE_LOCATION
permite a la API usar WiFi o datos móviles, o ambos, para determinar la ubicación del dispositivo. Los permisos ACCESS_FINE_LOCATION
permiten a la API usar el sistema de posicionamiento global (GPS), WiFi o datos móviles para determinar una ubicación lo más precisa posible.
Luego, cuando la aplicación intenta acceder a la ubicación del usuario, se muestra un mensaje solicitando acceso:
También se pueden habilitar estos permisos en el editor de manifiestos de Android de Visual Studio.
Especificar el permiso WRITE_EXTERNAL_STORAGE
Si la aplicación tiene como destino la API 22 o inferior, será necesario agregar el permiso WRITE_EXTERNAL_STORAGE
al manifiesto, como elemento secundario del elemento <manifest>
:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Esto no es necesario si la aplicación tiene como destino la API 23 o posterior.
Control Mapa
La clase Map define las siguientes propiedades que controlan su apariencia y comportamiento:
IsShowingUser
, de tipobool
, indica si el mapa muestra la ubicación actual del usuario.ItemsSource
, de tipoIEnumerable
, que especifica la colección de elementos de pin o marcaIEnumerable
que se van a mostrar.ItemTemplate
, de tipo DataTemplate, que especifica DataTemplate que se va a aplicar a cada elemento de la colección de marcadores mostrados.ItemTemplateSelector
, de tipo DataTemplateSelector, que especifica el DataTemplateSelector que se usará para elegir un DataTemplate para un marcador en tiempo de ejecución.IsScrollEnabled
, de tipobool
, determina si el mapa puede desplazarse.IsTrafficEnabled
, de tipobool
, indica si los datos de tráfico se superponen en el mapa.IsZoomEnabled
, de tipobool
, determina si en el mapa se puede aplicar zoom.MapElements
, de tipoIList<MapElement>
, representa la lista de elementos del mapa, como polígonos y polilíneas.MapType
, de tipoMapType
, indica el estilo de presentación del mapa.Pins
, de tipoIList<Pin>
, representa la lista de pines o marcas del mapa.VisibleRegion
, de tipoMapSpan
, devuelve la región mostrada actualmente del mapa.
Estas propiedades, con la excepción de las propiedades MapElements
, Pins
y VisibleRegion
están respaldadas por los objetos BindableProperty, lo que significa que estas propiedades pueden ser destinos de los enlaces de datos.
La clase Map define un evento MapClicked
que se desencadena cuando se pulsa en el mapa. El objeto MapClickedEventArgs
que acompaña al evento que tiene una propiedad de nombre Location
, de tipo Location
. Cuando se desencadena el evento, la propiedad Location
se establece en la ubicación del mapa que se ha pulsado. Para obtener información sobre la clase Location
, consulta Ubicación y distancia.
Para más información sobre las propiedades ItemsSource
, ItemTemplate
y ItemTemplateSelector
, consulta Mostrar una colección de pines.
Presentación de un mapa
Un Map se puede mostrar agregándolo a un diseño o una página:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps">
<maps:Map x:Name="map" />
</ContentPage>
El código de C# equivalente es el siguiente:
using Map = Microsoft.Maui.Controls.Maps.Map;
namespace WorkingWithMaps
{
public class MapTypesPageCode : ContentPage
{
public MapTypesPageCode()
{
Map map = new Map();
Content = map;
}
}
}
En este ejemplo se llama al constructor Map predeterminado, que centra el mapa en Maui, Hawái:
Como alternativa, se puede pasar un argumento MapSpan
a un constructor Map para establecer el punto central y el nivel de zoom del mapa cuando se carga. Para más información, consulta Presentación de una ubicación específica en un mapa.
Importante
.NET MAUI tiene dos tipos de Map
: Microsoft.Maui.Controls.Maps.Map y Microsoft.Maui.ApplicationModel.Map. Dado que el espacio de nombres Microsoft.Maui.ApplicationModel es una de las directivas global using
de .NET MAUI, al usar el control Microsoft.Maui.Controls.Maps.Map del código, tendrás que calificar completamente el uso de Map
completamente el uso o usar un alias de uso.
Tipos de mapas
La propiedad Map.MapType
se puede establecer en un miembro de enumeración MapType
para definir el estilo de presentación del mapa. La enumeración MapType
define los miembros siguientes:
Street
especifica que se mostrará un mapa de calles.Satellite
especifica que se mostrará un mapa que contiene imágenes de satélite.Hybrid
especifica que se mostrará un mapa que combina datos de calle y satélite.
De forma predeterminada, Map mostrará un mapa de calles si la propiedad MapType
no está definida. La propiedad MapType
se debe establecer en uno de los miembros de la enumeración MapType
:
<maps:Map MapType="Satellite" />
El código de C# equivalente es el siguiente:
Map map = new Map
{
MapType = MapType.Satellite
};
Mostrar una ubicación específica en un mapa
La región de un mapa que se va a mostrar cuando se carga un mapa se puede establecer pasando un argumento MapSpan
al constructor Map:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<x:Arguments>
<maps:MapSpan>
<x:Arguments>
<sensors:Location>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</sensors:Location>
<x:Double>0.01</x:Double>
<x:Double>0.01</x:Double>
</x:Arguments>
</maps:MapSpan>
</x:Arguments>
</maps:Map>
</ContentPage>
El código de C# equivalente es el siguiente:
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Location location = new Location(36.9628066, -122.0194722);
MapSpan mapSpan = new MapSpan(location, 0.01, 0.01);
Map map = new Map(mapSpan);
Este ejemplo 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 longitud representada por un objeto Location
y abarca 0,01 grados de latitud y 0,01 grados de longitud. Para obtener información sobre la clase Location
, consulta Ubicación y distancia. Para obtener información sobre cómo pasar argumentos en XAML, consulta Pasar argumentos en XAML.
El resultado es que, cuando se muestra el mapa, se centra en una ubicación específica y abarca un número específico de grados de latitud y longitud:
Creación de un objeto MapSpan
Hay varios enfoques para crear objetos MapSpan
. Un enfoque común es proporcionar los argumentos necesarios al constructor MapSpan
. Se trata de una latitud y longitud representadas por un objeto Location
y valores double
que representan los grados de latitud y longitud que abarca MapSpan
. Para obtener información sobre la clase Location
, consulta Ubicación y distancia.
Como alternativa, hay tres métodos en la clase MapSpan
que devuelven nuevos objetos MapSpan
:
ClampLatitude
devuelve un objetoMapSpan
con el mismoLongitudeDegrees
que la instancia de clase del método y un radio definido por sus argumentosnorth
ysouth
.FromCenterAndRadius
devuelve un objetoMapSpan
definido por sus argumentosLocation
yDistance
.WithZoom
devuelve un objetoMapSpan
con el mismo centro que la instancia de clase del método, pero con un radio multiplicado por su argumentodouble
.
Para obtener información sobre la estructura Distance
, consulta Ubicación y distancia.
Una vez creado MapSpan
, se puede acceder a las siguientes propiedades para recuperar datos sobre él:
Center
, de tipoLocation
, que representa la ubicación en el centro geográfico deMapSpan
.LatitudeDegrees
, de tipodouble
, que representa los grados de latitud que abarcaMapSpan
.LongitudeDegrees
, de tipodouble
, que representa los grados de longitud que abarcaMapSpan
.Radius
, de tipoDistance
, que representa el radioMapSpan
.
Mover el mapa
Se puede llamar al método Map.MoveToRegion
para cambiar la posición y el nivel de zoom de un mapa. Este método acepta un argumento MapSpan
que define la región del mapa que se va a mostrar y su nivel de zoom.
En el código siguiente se muestra un ejemplo de cómo mover la región mostrada en un mapa:
using Microsoft.Maui.Maps;
using Microsoft.Maui.Controls.Maps.Map;
...
MapSpan mapSpan = MapSpan.FromCenterAndRadius(location, Distance.FromKilometers(0.444));
map.MoveToRegion(mapSpan);
Acercamiento/alejamiento del mapa
El nivel de zoom de Map se puede cambiar sin modificar su ubicación. Esto se puede lograr mediante la interfaz de usuario de mapa o mediante programación llamando al método MoveToRegion
con un argumento MapSpan
que usa la ubicación actual como argumento Location
:
double zoomLevel = 0.5;
double latlongDegrees = 360 / (Math.Pow(2, zoomLevel));
if (map.VisibleRegion != null)
{
map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongDegrees, latlongDegrees));
}
En este ejemplo, se llama al método MoveToRegion
con un argumento MapSpan
que especifica la ubicación actual del mapa, a través de la propiedad Map.VisibleRegion
y el nivel de zoom como grados de latitud y longitud. El resultado general es que se cambia el nivel de zoom del mapa, pero su ubicación no. Un enfoque alternativo para implementar zoom en un mapa es usar el método MapSpan.WithZoom
para controlar el factor de zoom.
Importante
El zoom de un mapa, ya sea a través de la interfaz de usuario del mapa o mediante programación, requiere que la propiedad Map.IsZoomEnabled
sea true
. Para obtener más información sobre esta propiedad, consulta Deshabilitar el zoom.
Personalización del comportamiento del mapa
El comportamiento de Map se puede personalizar estableciendo algunas de sus propiedades y controlando el evento MapClicked
.
Nota:
Se puede lograr una personalización adicional del comportamiento del mapa mediante la personalización de su controlador. Para obtener más información, consulta Personalización de controles con controladores.
Mostrar datos del tráfico
La clase Map define una propiedad IsTrafficEnabled
de tipo bool
. De forma predeterminada, esta propiedad es false
, que indica que los datos de tráfico no se superponen en el mapa. Cuando esta propiedad se establece en true
, los datos de tráfico se superponen en el mapa:
<maps:Map IsTrafficEnabled="true" />
El código de C# equivalente es el siguiente:
Map map = new Map
{
IsTrafficEnabled = true
};
Deshabilitar el desplazamiento
La clase Map define una propiedad IsScrollEnabled
de tipo bool
. De forma predeterminada, esta propiedad es true
, que indica que el mapa puede desplazarse. Cuando esta propiedad se establece en false
, el mapa no se desplazará:
<maps:Map IsScrollEnabled="false" />
El código de C# equivalente es el siguiente:
Map map = new Map
{
IsScrollEnabled = false
};
Deshabilitar el zoom
La clase Map define una propiedad IsZoomEnabled
de tipo bool
. De forma predeterminada, esta propiedad es true
, que indica que el zoom se puede realizar en el mapa. Cuando esta propiedad se establece en false
, el mapa no se puede acercar:
<maps:Map IsZoomEnabled="false" />
El código de C# equivalente es el siguiente:
Map map = new Map
{
IsZoomEnabled = false
};
Obtener la ubicación del usuario
La clase Map define una propiedad IsShowingUser
de tipo bool
. De forma predeterminada, esta propiedad es false
, que indica que el mapa no muestra la ubicación actual del usuario. Cuando esta propiedad se establece en true
, el mapa muestra la ubicación actual del usuario:
<maps:Map IsShowingUser="true" />
El código de C# equivalente es el siguiente:
Map map = new Map
{
IsShowingUser = true
};
Importante
El acceso a la ubicación del usuario requiere que se hayan concedido permisos de ubicación a la aplicación. Para obtener más información, consulta Configuración de la plataforma.
Clics del mapa
La clase Map define un evento MapClicked
que se desencadena cuando el usuario pulsa el mapa. El objeto MapClickedEventArgs
que acompaña al evento que tiene una propiedad de nombre Location
, de tipo Location
. Cuando se desencadena el evento, la propiedad Location
se establece en la ubicación del mapa que se ha pulsado. Para obtener información sobre la clase Location
, consulta Ubicación y distancia.
En el ejemplo de código siguiente se muestra un controlador de eventos para el evento MapClicked
:
void OnMapClicked(object sender, MapClickedEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"MapClick: {e.Location.Latitude}, {e.Location.Longitude}");
}
En este ejemplo, el controlador de eventos OnMapClicked
genera la latitud y la longitud que representa la ubicación del mapa pulsado. El controlador de eventos debe registrarse con el evento MapClicked
:
<maps:Map MapClicked="OnMapClicked" />
El código de C# equivalente es el siguiente:
Map map = new Map();
map.MapClicked += OnMapClicked;
Ubicación y distancia
El espacio de nombres Microsoft.Maui.Devices.Sensors
contiene una clase Location
que se usa normalmente al colocar un mapa y sus marcadores. El espacio de nombres Microsoft.Maui.Maps
contiene una estructura Distance
que se puede usar opcionalmente al colocar un mapa.
Location
La clase Location
encapsula una ubicación almacenada como valores de latitud y longitud. Esta clase define las propiedades siguientes:
Accuracy
, de tipodouble?
, que representa la precisión horizontal deLocation
, en metros.Altitude
, de tipodouble?
, que representa la altitud en metros de un sistema de referencia especificado por la propiedadAltitudeReferenceSystem
.AltitudeReferenceSystem
, de tipoAltitudeReferenceSystem
, que especifica el sistema de referencia en el que se proporciona el valor de altitud.Course
, de tipodouble?
, que indica el valor en grados relativo al norte verdadero.IsFromMockProvider
, de tipobool
, que indica si la ubicación es del GPS o de un proveedor de ubicación ficticio.Latitude
, de tipodouble
, que representa la latitud de la ubicación en grados decimales.Longitude
, de tipodouble
, que representa la longitud de la ubicación en grados decimales.Speed
, de tipodouble?
, que representa la velocidad en metros por segundo.Timestamp
, de tipoDateTimeOffset
, que representa la marca de tiempo cuando se creóLocation
.VerticalAccuracy
, de tipodouble?
, que especifica la precisión vertical deLocation
, en metros.
Los objetos Location
se crean con una de las sobrecargas del constructor Location
, que normalmente requieren argumentos de latitud y longitud mínimos especificados como valores double
:
Location location = new Location(36.9628066, -122.0194722);
Al crear un objeto Location
, el valor de latitud se fijará entre -90,0 y 90,0, y el valor de longitud se fijará entre -180,0 y 180,0.
Nota:
La clase GeographyUtils
tiene un método de extensión ToRadians
que convierte un valor double
de grados a radianes y un método de extensión ToDegrees
que convierte un valor double
de radianes a grados.
La clase Location
también tiene métodos CalculateDistance
para calcular la distancia entre dos ubicaciones.
Distancia
La estructura Distance
encapsula una distancia almacenada como un valor double
, que representa la distancia en metros. Esta estructura define tres propiedades de solo lectura:
Kilometers
, de tipodouble
, que representa la distancia en kilómetros que abarcaDistance
.Meters
, de tipodouble
, que representa la distancia en metros que abarcaDistance
.Miles
, de tipodouble
, que representa la distancia en millas que abarcaDistance
.
Los objetos Distance
se pueden crear con el constructor Distance
, que requiere un argumento de metros especificado como double
:
Distance distance = new Distance(1450.5);
Como alternativa, los objetos Distance
se pueden crear con los métodos de fábrica FromKilometers
FromMeters
, FromMiles
y BetweenPositions
:
Distance distance1 = Distance.FromKilometers(1.45); // argument represents the number of kilometers
Distance distance2 = Distance.FromMeters(1450.5); // argument represents the number of meters
Distance distance3 = Distance.FromMiles(0.969); // argument represents the number of miles
Distance distance4 = Distance.BetweenPositions(location1, location2);
Chinchetas
El control Map 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 tipo
string
, que normalmente representa el título del pin o marca. Location
, de tipoLocation
, 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="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map x:Name="map">
<x:Arguments>
<maps:MapSpan>
<x:Arguments>
<sensors:Location>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</sensors:Location>
<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.Location>
<sensors:Location>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</sensors:Location>
</maps:Pin.Location>
</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 Location
, 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 Location
. Para obtener información sobre la clase Location
, consulta Ubicación y distancia. Para más información sobre cómo pasar argumentos en XAML a objetos que carecen de constructores predeterminados, consulta Pasar argumentos en XAML.
El código de C# equivalente es el siguiente:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Map map = new Map
{
...
};
Pin pin = new Pin
{
Label = "Santa Cruz",
Address = "The city with a boardwalk",
Type = PinType.Place,
Location = new Location(36.9628066, -122.0194722)
};
map.Pins.Add(pin);
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 Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Pin boardwalkPin = new Pin
{
Location = new Location(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
{
Location = new Location(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, debes personalizar el controlador Pin
para personalizar la apariencia del pin o marca. Para más información sobre la personalización del controlador, consulta Personalización de controles con controladores.
Presentación de una colección de pin
La clase Map define las propiedades enlazables siguientes:
ItemsSource
, de tipoIEnumerable
, que especifica la colección de elementos de pin o marcaIEnumerable
que se van a mostrar.ItemTemplate
, de tipo DataTemplate, que especifica DataTemplate que se va a aplicar a cada elemento de la colección de marcadores mostrados.ItemTemplateSelector
, de tipo DataTemplateSelector, que especifica el DataTemplateSelector que se usará para elegir un DataTemplate para un marcador 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:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps">
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Positions}">
<maps:Map.ItemTemplate>
<DataTemplate>
<maps:Pin Location="{Binding Location}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</maps:Map.ItemTemplate>
</maps:Map>
...
</Grid>
</ContentPage>
Los datos de propiedad ItemsSource
se enlazan a la propiedad Positions
del modelo de vista conectado, que devuelve ObservableCollection
de objetos Position
, que es un tipo personalizado. Cada objeto Position
define las propiedades Address
y Description
, de tipo string
, y una propiedad Location
, de tipo Location
.
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 la captura de pantalla siguiente se muestra Map que muestra una colección 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:templates="clr-namespace:WorkingWithMaps.Templates"
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps">
<ContentPage.Resources>
<templates:MapItemTemplateSelector x:Key="MapItemTemplateSelector">
<templates:MapItemTemplateSelector.DefaultTemplate>
<DataTemplate>
<maps:Pin Location="{Binding Location}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</templates:MapItemTemplateSelector.DefaultTemplate>
<templates:MapItemTemplateSelector.SanFranTemplate>
<DataTemplate>
<maps:Pin Location="{Binding Location}"
Address="{Binding Address}"
Label="Xamarin!" />
</DataTemplate>
</templates:MapItemTemplateSelector.SanFranTemplate>
</templates:MapItemTemplateSelector>
</ContentPage.Resources>
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Positions}"
ItemTemplateSelector="{StaticResource MapItemTemplateSelector}">
...
</Grid>
</ContentPage>
En el ejemplo siguiente se muestra la clase MapItemTemplateSelector
:
using WorkingWithMaps.Models;
namespace WorkingWithMaps.Templates;
public class MapItemTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate SanFranTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((Position)item).Address.Contains("San Francisco") ? SanFranTemplate : DefaultTemplate;
}
}
La clase MapItemTemplateSelector
define propiedades DataTemplate DefaultTemplate
y SanFranTemplate
que se establecen en diferentes plantillas de datos. El método OnSelectTemplate
devuelve SanFranTemplate
, 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 de subclases Pin
a diferentes propiedades, en función del subtipo Pin
.
Para más información sobre los selectores de plantillas de datos, consulta Creación de DataTemplateSelector.
Polígonos, polilíneas y círculos
Los elementos Polygon
, Polyline
y Circle
permiten resaltar áreas específicas en un mapa. Polygon
es una forma completamente cerrada que puede tener un trazo y un color de relleno. Polyline
es una línea que no incluye completamente un área. Circle
resalta de un área circular del mapa:
Las clases Polygon
, Polyline
y Circle
derivan de la clase MapElement
, que expone las siguientes propiedades enlazables:
StrokeColor
es un objeto Color que determina el color de línea.StrokeWidth
es un objetofloat
que determina el ancho de línea.
La clase Polygon
define una propiedad enlazable adicional:
FillColor
es un objeto Color que determina el color de fondo del polígono.
Además, las clases Polygon
y Polyline
definen una propiedad GeoPath
, que es una lista de objetos Location
que especifican los puntos de la forma.
La clase Circle
define las propiedades enlazables siguientes:
Center
es un objetoLocation
que define el centro del círculo, en latitud y longitud.Radius
es un objetoDistance
que define el radio del círculo en metros, kilómetros o millas.FillColor
es una propiedad Color que determina el color dentro del perímetro del círculo.
Creación de un polígono
Un objeto Polygon
se puede agregar a un mapa creando una instancia de él y agregándolo a la colección MapElements
del mapa:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<maps:Map.MapElements>
<maps:Polygon StrokeColor="#FF9900"
StrokeWidth="8"
FillColor="#88FF9900">
<maps:Polygon.Geopath>
<sensors:Location>
<x:Arguments>
<x:Double>47.6458676</x:Double>
<x:Double>-122.1356007</x:Double>
</x:Arguments>
</sensors:Location>
<sensors:Location>
<x:Arguments>
<x:Double>47.6458097</x:Double>
<x:Double>-122.142789</x:Double>
</x:Arguments>
</sensors:Location>
...
</maps:Polygon.Geopath>
</maps:Polygon>
</maps:Map.MapElements>
</maps:Map>
</ContentPage>
El código de C# equivalente es el siguiente:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Map map = new Map();
// Instantiate a polygon
Polygon polygon = new Polygon
{
StrokeWidth = 8,
StrokeColor = Color.FromArgb("#1BA1E2"),
FillColor = Color.FromArgb("#881BA1E2"),
Geopath =
{
new Location(47.6368678, -122.137305),
new Location(47.6368894, -122.134655),
...
}
};
// Add the polygon to the map's MapElements collection
map.MapElements.Add(polygon);
Las propiedades StrokeColor
y StrokeWidth
se especifican para establecer el contorno del polígono. En este ejemplo, el valor de propiedad FillColor
coincide con el valor de propiedad StrokeColor
, pero tiene un valor alfa especificado para que sea transparente, lo que permite que el mapa subyacente sea visible a través de la forma. La propiedad GeoPath
contiene una lista de objetos Location
que definen las coordenadas geográficas de los puntos del polígono. Un objeto Polygon
se representa en el mapa una vez que se ha agregado a la colección MapElements
de Map.
Nota:
Polygon
es una forma totalmente cerrada. Los puntos primero y último se conectarán automáticamente si no coinciden.
Creación de una polilínea
Un objeto Polyline
se puede agregar a un mapa creando una instancia de él y agregándolo a la colección MapElements
del mapa:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<maps:Map.MapElements>
<maps:Polyline StrokeColor="Black"
StrokeWidth="12">
<maps:Polyline.Geopath>
<sensors:Location>
<x:Arguments>
<x:Double>47.6381401</x:Double>
<x:Double>-122.1317367</x:Double>
</x:Arguments>
</sensors:Location>
<sensors:Location>
<x:Arguments>
<x:Double>47.6381473</x:Double>
<x:Double>-122.1350841</x:Double>
</x:Arguments>
</sensors:Location>
...
</maps:Polyline.Geopath>
</maps:Polyline>
</maps:Map.MapElements>
</maps:Map>
</ContentPage>
El código de C# equivalente es el siguiente:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Map map = new Map();
// instantiate a polyline
Polyline polyline = new Polyline
{
StrokeColor = Colors.Blue,
StrokeWidth = 12,
Geopath =
{
new Location(47.6381401, -122.1317367),
new Location(47.6381473, -122.1350841),
...
}
};
// Add the Polyline to the map's MapElements collection
map.MapElements.Add(polyline);
Las propiedades StrokeColor
y StrokeWidth
se especifican para establecer la apariencia de la línea. La propiedad GeoPath
contiene una lista de objetos Location
que definen las coordenadas geográficas de los puntos de polilínea. Un objeto Polyline
se representa en el mapa una vez que se ha agregado a la colección MapElements
de Map.
Creación de un círculo
Un objeto Circle
se puede agregar a un mapa creando una instancia de él y agregándolo a la colección MapElements
del mapa:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<maps:Map.MapElements>
<maps:Circle StrokeColor="#88FF0000"
StrokeWidth="8"
FillColor="#88FFC0CB">
<maps:Circle.Center>
<sensors:Location>
<x:Arguments>
<x:Double>37.79752</x:Double>
<x:Double>-122.40183</x:Double>
</x:Arguments>
</sensors:Location>
</maps:Circle.Center>
<maps:Circle.Radius>
<maps:Distance>
<x:Arguments>
<x:Double>250</x:Double>
</x:Arguments>
</maps:Distance>
</maps:Circle.Radius>
</maps:Circle>
</maps:Map.MapElements>
</maps:Map>
</ContentPage>
El código de C# equivalente es el siguiente:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
Map map = new Map();
// Instantiate a Circle
Circle circle = new Circle
{
Center = new Location(37.79752, -122.40183),
Radius = new Distance(250),
StrokeColor = Color.FromArgb("#88FF0000"),
StrokeWidth = 8,
FillColor = Color.FromArgb("#88FFC0CB")
};
// Add the Circle to the map's MapElements collection
map.MapElements.Add(circle);
La ubicación de Circle
en el mapa viene determinada por el valor de las propiedades Center
y Radius
. La propiedad Center
define el centro del círculo, en latitud y longitud, mientras que la propiedad Radius
define el radio del círculo en metros. Las propiedades StrokeColor
y StrokeWidth
se especifican para establecer el contorno del círculo. El valor de la propiedad FillColor
especifica el color dentro del perímetro del círculo. En este ejemplo, ambos valores de color especifican un canal alfa, lo que permite que el mapa subyacente sea visible a través del círculo. El objeto Circle
se representa en el mapa una vez que se ha agregado a la colección MapElements
de Map.
Nota:
La clase GeographyUtils
tiene un método de extensión ToCircumferencePositions
que convierte un objeto Circle
(que define valores de propiedad Center
y Radius
) en una lista de objetos Location
que componen las coordenadas de latitud y longitud del perímetro del círculo.
Geocodificación y geolocalización
La clase Geocoding
en el espacio de nombres Microsoft.Maui.Devices.Sensors
puede usarse para geocodificar una marca de posición en coordenadas de posición e invertir las coordenadas de código geográfico a una marca de posición. Para más información, consulta Geocodificación.
La clase Geolocation
, en el espacio de nombres Microsoft.Maui.Devices.Sensors
, se puede usar para recuperar las coordenadas de geolocalización actuales del dispositivo. Para obtener más información, consulta Geolocalización.
Inicio de la aplicación de mapa nativa
La aplicación de mapa nativo en cada plataforma se puede iniciar desde una aplicación . NET MAUI mediante la clase Launcher
. Esta clase permite que una aplicación abra otra aplicación a través de su esquema de URI personalizado. Las funciones del iniciador se pueden invocar con el método OpenAsync
, pasando un argumento string
o Uri
que representa el esquema de dirección URL personalizado que se va a abrir. Para más información sobre la clase Launcher
, consulta Launcher.
Nota:
Una alternativa al uso de la clase Launcher
es usar la clase Map del espacio de nombres Microsoft.Maui.ApplicationModel
. Para más información, consulta Mapa.
La aplicación de mapas en cada plataforma usa un esquema de URI personalizado único. Para más información sobre el esquema de URI de mapas en iOS, consulta Vínculos de mapas en developer.apple.com. Para más información sobre el esquema de URI de mapas en Android, consulta Maps Developer Guide y Google Intents for Android en developers.android.com. Para más información sobre el esquema de URI de mapas en Windows, consulta Iniciar la aplicación Mapas de Windows.
Inicio de la aplicación de mapa en una ubicación específica
Se puede abrir una ubicación en la aplicación nativa de mapas agregando parámetros de consulta adecuados al esquema de URI personalizado para cada aplicación de mapa:
if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
{
// https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
await Launcher.OpenAsync("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
{
// opens the Maps app directly
await Launcher.OpenAsync("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
{
await Launcher.OpenAsync("bingmaps:?where=394 Pacific Ave San Francisco CA");
}
El resultado de este código de ejemplo es que la aplicación de mapa nativa se inicia en cada plataforma y el mapa aparece centrado en un pin o marca que representa la ubicación especificada.
Inicio de la aplicación de mapa con direcciones
La aplicación nativa de mapas se puede iniciar mostrando direcciones, agregando parámetros de consulta adecuados al esquema de URI personalizado para cada aplicación de mapa:
if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
{
// https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
await Launcher.OpenAsync("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
{
// opens the 'task chooser' so the user can pick Maps, Chrome or other mapping app
await Launcher.OpenAsync("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
{
await Launcher.OpenAsync("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052");
}
El resultado de este código de ejemplo es que la aplicación de mapa nativa se inicia en cada plataforma, con el mapa centrado en una ruta entre las ubicaciones especificadas.