Compartir a través de


Asignar

Examinar ejemplo. Examina el ejemplo

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:

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:

Captura de pantalla de la solicitud de permiso de ubicación en iOS.

Android

El proceso de configuración para mostrar e interactuar con un mapa en Android es:

  1. Obtén una clave de API de Google Maps y agrégala al manifiesto de la aplicación.
  2. Especifica el número de versión de Google Play Services en el manifiesto.
  3. [opcional] Especifica los permisos de ubicación en el manifiesto.
  4. [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:

Captura de pantalla de la solicitud de permiso de ubicación en Android.

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 tipo bool, indica si el mapa muestra la ubicación actual del usuario.
  • ItemsSource, de tipo IEnumerable, que especifica la colección de elementos de pin o marca IEnumerable 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 tipo bool, determina si el mapa puede desplazarse.
  • IsTrafficEnabled, de tipo bool, indica si los datos de tráfico se superponen en el mapa.
  • IsZoomEnabled, de tipo bool, determina si en el mapa se puede aplicar zoom.
  • MapElements, de tipo IList<MapElement>, representa la lista de elementos del mapa, como polígonos y polilíneas.
  • MapType, de tipo MapType, indica el estilo de presentación del mapa.
  • Pins, de tipo IList<Pin>, representa la lista de pines o marcas del mapa.
  • VisibleRegion, de tipo MapSpan, 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:

Captura de pantalla del control de mapa con la ubicación predeterminada.

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:

Captura de pantalla del control de mapa con la ubicación especificada.

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:

  1. ClampLatitude devuelve un objeto MapSpan con el mismo LongitudeDegrees que la instancia de clase del método y un radio definido por sus argumentos north y south.
  2. FromCenterAndRadius devuelve un objeto MapSpan definido por sus argumentos Location y Distance.
  3. WithZoom devuelve un objeto MapSpan con el mismo centro que la instancia de clase del método, pero con un radio multiplicado por su argumento double.

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 tipo Location, que representa la ubicación en el centro geográfico de MapSpan.
  • LatitudeDegrees, de tipo double, que representa los grados de latitud que abarca MapSpan.
  • LongitudeDegrees, de tipo double, que representa los grados de longitud que abarca MapSpan.
  • Radius, de tipo Distance, que representa el radio MapSpan.

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 tipo double?, que representa la precisión horizontal de Location, en metros.
  • Altitude, de tipo double?, que representa la altitud en metros de un sistema de referencia especificado por la propiedad AltitudeReferenceSystem.
  • AltitudeReferenceSystem, de tipo AltitudeReferenceSystem, que especifica el sistema de referencia en el que se proporciona el valor de altitud.
  • Course, de tipo double?, que indica el valor en grados relativo al norte verdadero.
  • IsFromMockProvider, de tipo bool, que indica si la ubicación es del GPS o de un proveedor de ubicación ficticio.
  • Latitude, de tipo double, que representa la latitud de la ubicación en grados decimales.
  • Longitude, de tipo double, que representa la longitud de la ubicación en grados decimales.
  • Speed, de tipo double?, que representa la velocidad en metros por segundo.
  • Timestamp, de tipo DateTimeOffset, que representa la marca de tiempo cuando se creó Location.
  • VerticalAccuracy, de tipo double?, que especifica la precisión vertical de Location, 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 tipo double, que representa la distancia en kilómetros que abarca Distance.
  • Meters, de tipo double, que representa la distancia en metros que abarca Distance.
  • Miles, de tipo double, que representa la distancia en millas que abarca Distance.

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 FromKilometersFromMeters, 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:

Captura de pantalla de un chincheta en el mapa y su ventana de información.

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 tipo string, que normalmente representa la dirección de la ubicación de la marca o pin. Sin embargo, puede ser cualquier contenido string, no solo una dirección.
  • Label, de tipo string, que normalmente representa el título del pin o marca.
  • Location, de tipo Location, que representa la latitud y la longitud del pin o marca.
  • Type, de tipo PinType, 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:

Captura de pantalla de una chincheta en el mapa.

Interacción con un pin

De forma predeterminada, cuando se pulsa en un Pin, aparece la ventana de información:

Captura de pantalla de una chincheta en el mapa y su 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 tipo IEnumerable, que especifica la colección de elementos de pin o marca IEnumerable 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:

Captura de pantalla del mapa con chinchetas enlazadas a 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 las propiedades DefaultTemplate y SanFranTemplateDataTemplate que se establecen en plantillas de datos diferentes. 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:

Polígono y polilínea en un mapa.Círculo en un 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 objeto float 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 objeto Location que define el centro del círculo, en latitud y longitud.
  • Radius es un objeto Distance 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.