Поделиться через


Карта

Просмотр образца. Просмотр образца

Элемент управления Map в .NET MAUI — это кроссплатформенное средство для отображения и аннотирования карт. Элемент управления Map использует встроенный элемент управления картой на каждой платформе и предоставляется пакетом NuGet Microsoft.Maui.Controls.Maps.

Важный

Элемент управления Map не поддерживается в Windows из-за отсутствия элемента управления картой в WinUI. Однако пакет NuGet CommunityToolkit.Maui.Maps предоставляет доступ к Картам Bing через WebView в системе Windows. Дополнительную информацию см. в разделе Как начать.

Настройка

Элемент управления Map использует собственный элемент управления картой на каждой платформе. Это обеспечивает быстрый и знакомый интерфейс карт для пользователей, но означает, что некоторые действия по настройке необходимы для соблюдения требований API для каждой платформы.

Инициализация карты

Элемент управления Map предоставляется пакетом NuGet Microsoft.Maui.Controls.Maps, который следует добавить в проект приложения .NET MAUI.

После установки пакета NuGet его необходимо инициализировать в приложении, вызвав метод UseMauiMaps объекта MauiAppBuilder в методе CreateMauiApp класса MauiProgram:

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();
    }
}

После добавления и инициализации пакета NuGet Map API можно использовать в проекте.

Конфигурация платформы

Дополнительная конфигурация требуется в Android, прежде чем карта будет отображаться. Кроме того, в iOS, Android и Mac Catalyst доступ к расположению пользователя требует предоставления приложению разрешений на расположение.

IOS и Mac Catalyst

Отображение и взаимодействие с картой в iOS и Mac Catalyst не требует дополнительной настройки. Однако для доступа к службам расположения необходимо указать нужные запросы служб расположения в Info.plist. Обычно они будут одним или несколькими из следующих:

Для получения дополнительной информации см. на сайте developer.apple.com раздел «Выбор уровня доступа к службам геолокации для запроса».

Ниже показано xml-представление этих ключей в Info.plist. Необходимо обновить значения string, чтобы отразить, как ваше приложение использует сведения о расположении:

<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>

Затем появится запрос, когда приложение пытается получить доступ к расположению пользователя, запрашивая доступ:

снимок экрана запроса на разрешение на доступ к местоположению в iOS.

Андроид

Процесс конфигурации для отображения и взаимодействия с картой в Android — это:

  1. Получите ключ API Google Maps и добавьте его в манифест приложения.
  2. Укажите номер версии служб Google Play в манифесте.
  3. [необязательно] Укажите разрешения расположения в манифесте.
  4. [необязательно] Укажите разрешение WRITE_EXTERNAL_STORAGE в манифесте.
Получение ключа API Google Maps

Чтобы использовать элемент управления Map на Android, необходимо создать ключ API, который будет использоваться пакетом SDK Google Maps , от которого элемент управления Map зависит в Android. Для этого следуйте инструкциям по настройке в Google Cloud Console и использованию ключей API на developers.google.com.

Получив ключ API, его необходимо добавить в элемент <application> файла Platform/Android/AndroidManifest.xml, указав его в качестве значения метаданных 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>

Это внедряет ключ API в манифест. Без допустимого ключа API элемент управления Map отобразит пустую сетку.

Заметка

com.google.android.geo.API_KEY — это рекомендуемое имя метаданных для ключа API. Ключ с таким именем можно использовать для проверки подлинности нескольких API на основе Google Maps в Android. Для обратной совместимости можно использовать имя метаданных com.google.android.maps.v2.API_KEY, но разрешает только проверку подлинности в Android Maps API v2. Приложение может указать только одно из имен метаданных ключа API.

Укажите номер версии служб Google Play

Добавьте следующее объявление в элемент <application>AndroidManifest.xml:

<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

Это внедряет версию служб Google Play, с которыми было скомпилировано приложение, в манифест.

Указание разрешений на доступ к местоположению

Если вашему приложению необходимо получить доступ к геопозиции пользователя, вы должны запросить разрешение, добавив разрешение ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION (или оба) в манифест в качестве дочернего элемента <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>

Разрешение ACCESS_COARSE_LOCATION позволяет API использовать wi-fi или мобильные данные или оба, чтобы определить расположение устройства. Разрешения ACCESS_FINE_LOCATION позволяют API использовать глобальную систему позиционирования (GPS), Wi-Fi или мобильные данные, чтобы определить точное расположение.

Затем появится запрос, когда приложение пытается получить доступ к расположению пользователя, запрашивая доступ:

снимок экрана запроса на разрешение на доступ к данным о местоположении на Android.

Кроме того, эти разрешения можно включить в редакторе манифестов Android в Visual Studio.

Укажите разрешение WRITE_EXTERNAL_STORAGE, которое позволяет приложению записывать данные на внешнее хранилище.

Если приложение предназначено для API 22 или ниже, необходимо добавить разрешение WRITE_EXTERNAL_STORAGE в манифест в качестве дочернего элемента <manifest>:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Это не обязательно, если приложение предназначено для API 23 или более поздней версии.

Элемент управления картой

Класс Map определяет следующие свойства, управляющие внешним видом и поведением карты:

  • IsShowingUserтипа boolуказывает, отображается ли карта текущего расположения пользователя.
  • ItemsSourceтипа IEnumerable, который указывает коллекцию элементов закрепления IEnumerable для отображения.
  • ItemTemplateтипа DataTemplate, который задает DataTemplate, чтобы применить к каждому элементу в коллекции отображаемых значков.
  • ItemTemplateSelectorтипа DataTemplateSelector, который указывает DataTemplateSelector, который будет использоваться для выбора DataTemplate для пин-кода во время выполнения.
  • IsScrollEnabledтипа boolопределяет, разрешено ли прокручивать карту.
  • IsTrafficEnabledтипа boolуказывает, нанесены ли данные о движении на карту.
  • IsZoomEnabledтипа boolопределяет, разрешено ли масштабирование карты.
  • MapElementsтипа IList<MapElement>представляет список элементов на карте, таких как многоугольники и многолинейные линии.
  • MapTypeтипа MapTypeуказывает стиль отображения карты.
  • Pinsтипа IList<Pin>представляет список меток на карте.
  • VisibleRegionтипа MapSpanвозвращает регион карты, который отображается в данный момент.

Эти свойства, за исключением MapElements, Pinsи VisibleRegion свойств, поддерживаются объектами BindableProperty, что означает, что они могут быть целевыми объектами привязки данных.

Класс Map также определяет событие MapClicked, которое запускается при нажатии карты. Объект MapClickedEventArgs, который сопровождает событие, имеет единственное свойство с именем Locationтипа Location. При срабатывании события свойству Location присваивается местоположение на карте, в которое произошло касание. Сведения о классе Location см. в разделе Расположение и расстояние.

Сведения о свойствах ItemsSource, ItemTemplateи ItemTemplateSelector см. в разделе Отображение коллекции закреплений.

Отображение карты

Map можно отобразить, добавив его в макет или страницу:

<ContentPage ...
             xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps">
    <maps:Map x:Name="map" />
</ContentPage>

Эквивалентный код C#:

using Map = Microsoft.Maui.Controls.Maps.Map;

namespace WorkingWithMaps
{
    public class MapTypesPageCode : ContentPage
    {
        public MapTypesPageCode()
        {
            Map map = new Map();
            Content = map;
        }
    }
}

В этом примере вызывается конструктор Map по умолчанию, который располагает карту в центре острова Мауи, Гавайи.

снимок экрана элемента управления картой с расположением по умолчанию.

Кроме того, аргумент MapSpan можно передать в конструктор Map, чтобы задать центральную точку и уровень масштабирования карты при загрузке. Дополнительные сведения см. в разделе Отображение определенного расположения на карте.

Важный

.NET MAUI имеет два типа MapMicrosoft.Maui.Controls.Maps.Map и Microsoft.Maui.ApplicationModel.Map. Так как пространство имен Microsoft.Maui.ApplicationModel является одной из директив global using в .NET MAUI, при использовании элемента управления Microsoft.Maui.Controls.Maps.Map из кода необходимо полностью квалифицировать использование Map или воспользоваться с псевдонимом.

Типы карт

Свойство Map.MapType можно задать элементом перечисления MapType, чтобы определить стиль отображения карты. Перечисление MapType определяет следующие элементы:

  • Street указывает, что будет отображаться карта улиц.
  • Satellite указывает, что будет отображаться карта, содержащая спутниковые изображения.
  • Hybrid указывает, что будет отображаться карта, объединяющая данные улиц и спутников.

По умолчанию Map будет отображать карту улиц, если свойство MapType не определено. Кроме того, свойство MapType можно задать для одного из элементов перечисления MapType:

<maps:Map MapType="Satellite" />

Эквивалентный код C#:

Map map = new Map
{
    MapType = MapType.Satellite
};

Отображение определенного расположения на карте

Область карты, отображаемой при загрузке карты, можно задать путем передачи аргумента MapSpan конструктору 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>

Эквивалентный код C#:

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);

В этом примере создается объект Map, показывающий регион, заданный объектом MapSpan. Объект MapSpan сосредоточен на широте и долготе, представленной объектом Location, и охватывает 0,01 широты и 0,01 градуса долготы. Сведения о классе Location см. в разделе Расположение и расстояние. Сведения о передаче аргументов в XAML можно найти в разделе Pass arguments in XAML.

Результатом является то, что при отображении карты он сосредоточен на определенном расположении и охватывает определенное количество широт и долгот:

снимок экрана элемента управления картой с указанным расположением.

Создание объекта MapSpan

Существует ряд подходов к созданию объектов MapSpan. Распространенный подход заключается в предоставлении необходимых аргументов конструктору MapSpan. Это широта и долгота, представленные объектом Location, и double значения, представляющие градусы широты и долготы, охватываемые MapSpan. Сведения о классе Location см. в разделе Расположение и расстояние.

Кроме того, в классе MapSpan есть три метода, которые возвращают новые объекты MapSpan:

  1. ClampLatitude возвращает MapSpan с тем же LongitudeDegrees, что и экземпляр класса метода, и радиус, который определяется его аргументами north и south.
  2. FromCenterAndRadius возвращает MapSpan, определяемый его аргументами Location и Distance.
  3. WithZoom возвращает MapSpan с тем же центром, что и экземпляр класса метода, но с радиусом, умноженным на его аргумент double.

Сведения о структуре Distance см. в разделе Расположение и расстояние.

После создания MapSpan можно получить доступ к следующим свойствам, чтобы получить данные об этом:

  • Centerтипа Location, представляющий расположение в географическом центре MapSpan.
  • LatitudeDegreesтипа double, который представляет степень широты, охватываемой MapSpan.
  • LongitudeDegreesтипа double, который представляет степень долготы, охватываемой MapSpan.
  • Radiusтипа Distance, который представляет радиус MapSpan.

Перемещение карты

Метод Map.MoveToRegion можно вызвать для изменения положения и масштаба карты. Этот метод принимает аргумент MapSpan, определяющий область отображения карты и его уровень масштабирования.

В следующем коде показан пример перемещения отображаемой области на карте:

using Microsoft.Maui.Maps;
using Microsoft.Maui.Controls.Maps.Map;
...

MapSpan mapSpan = MapSpan.FromCenterAndRadius(location, Distance.FromKilometers(0.444));
map.MoveToRegion(mapSpan);

Масштабирование карты

Уровень масштабирования Map можно изменить, не изменив его расположение. Это можно сделать с помощью пользовательского интерфейса карты или программно путем вызова метода MoveToRegion с аргументом MapSpan, который использует текущее расположение в качестве аргумента 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));
}

В этом примере метод MoveToRegion вызывается с аргументом MapSpan, который указывает текущее расположение карты через свойство Map.VisibleRegion и уровень масштабирования в виде градусов широты и долготы. Общий результат заключается в том, что уровень масштабирования карты изменяется, но она остаётся на месте. Альтернативный подход к реализации масштабирования карты — использовать метод MapSpan.WithZoom для управления коэффициентом масштабирования.

Важный

Масштабирование карты с помощью пользовательского интерфейса карты или программы требует, чтобы свойство Map.IsZoomEnabled было true. Дополнительные сведения об этом свойстве см. в разделе Отключение масштабирования.

Настройка поведения карты

Поведение Map можно настроить, задав некоторые его свойства и обрабатывая событие MapClicked.

Заметка

Дополнительная настройка поведения карты может быть достигнута путем настройки обработчика. Дополнительные сведения см. в разделе Настройка элементов управления с помощью обработчиков.

Отображение данных трафика

Класс Map определяет свойство IsTrafficEnabled типа bool. По умолчанию это свойство false, что указывает на то, что данные трафика не будут отображаться на карте. Если для этого свойства задано значение true, данные трафика накладываются на карту:

<maps:Map IsTrafficEnabled="true" />

Эквивалентный код C#:

Map map = new Map
{
    IsTrafficEnabled = true
};

Отключение прокрутки

Класс Map определяет свойство IsScrollEnabled типа bool. По умолчанию это свойство true, указывающее, что карта разрешена для прокрутки. Если для этого свойства задано значение false, карта не будет прокручиваться:

<maps:Map IsScrollEnabled="false" />

Эквивалентный код C#:

Map map = new Map
{
    IsScrollEnabled = false
};

Отключение масштабирования

Класс Map определяет свойство IsZoomEnabled типа bool. По умолчанию это свойство true, указывающее, что масштабирование можно выполнить на карте. Если для этого свойства задано значение false, карта не может быть увеличена:

<maps:Map IsZoomEnabled="false" />

Эквивалентный код C#:

Map map = new Map
{
    IsZoomEnabled = false
};

Отображение расположения пользователя

Класс Map определяет свойство IsShowingUser типа bool. По умолчанию это свойство false, указывающее, что карта не отображает текущее расположение пользователя. Если для этого свойства задано значение true, на карте отображается текущее расположение пользователя:

<maps:Map IsShowingUser="true" />

Эквивалентный код C#:

Map map = new Map
{
    IsShowingUser = true
};

Важный

Для доступа к расположению пользователя требуется разрешение на расположение, которое было предоставлено приложению. Дополнительные сведения см. в конфигурации платформы.

Нажатия на карту

Класс Map определяет событие MapClicked, которое запускается при нажатии карты. Объект MapClickedEventArgs, который сопровождает событие, имеет одно свойство с именем Locationтипа Location. При срабатывании события свойство Location задается расположением карты, по которому было нажато. Сведения о классе Location см. в разделе Расположение и расстояние.

В следующем примере кода показан обработчик событий для события MapClicked:

void OnMapClicked(object sender, MapClickedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine($"MapClick: {e.Location.Latitude}, {e.Location.Longitude}");
}

В этом примере обработчик событий OnMapClicked выводит широту и долготу, представляющие место на карте, выбранное нажатием. Обработчик событий должен быть зарегистрирован в событии MapClicked:

<maps:Map MapClicked="OnMapClicked" />

Эквивалентный код C#:

Map map = new Map();
map.MapClicked += OnMapClicked;

Расположение и расстояние

Пространство имен Microsoft.Maui.Devices.Sensors содержит класс Location, который обычно используется при расположении карты и её меток. Пространство имен Microsoft.Maui.Maps содержит структуру Distance, которую можно использовать по выбору при расположении карты.

Местоположение

Класс Location инкапсулирует расположение, хранящееся в виде значений широты и долготы. Этот класс определяет следующие свойства:

  • Accuracyтипа double?, представляющая горизонтальную точность Locationв метрах.
  • Altitudeтипа double?, представляющий высоту в метрах в системе отсчета, определяемой свойством AltitudeReferenceSystem.
  • AltitudeReferenceSystemтипа AltitudeReferenceSystem, который указывает эталонную систему, в которой предоставляется значение высоты.
  • Courseтипа double?, указывающее значение градусов относительно истинного севера.
  • IsFromMockProviderтипа bool, который указывает, является ли местоположение от GPS или симулятора местоположения.
  • Latitudeтипа double, который представляет географическую широту в десятичных градусах.
  • Longitudeтипа double, представляющий собой долготу местоположения в десятичных градусах.
  • Speedтипа double?, который представляет скорость в метрах в секунду.
  • Timestampтипа DateTimeOffset, представляющий отметку времени, когда был создан Location.
  • VerticalAccuracy, типа double?, который указывает вертикальную точность Locationв метрах.

Location объекты создаются с помощью одной из перегрузок конструктора Location, которые обычно требуют широты и долготы в качестве минимально необходимых аргументов, указанных как значения double.

Location location = new Location(36.9628066, -122.0194722);

При создании объекта Location значение широты будет зажато в диапазоне от –90,0 до 90,0, а значение долготы будет зажато в диапазоне от –180,0 до 180,0.

Заметка

Класс GeographyUtils имеет метод расширения ToRadians, который преобразует значение double из градусов в радианы и метод расширения ToDegrees, который преобразует значение double из радианов в градусы.

Класс Location также имеет методы CalculateDistance, которые вычисляют расстояние между двумя расположениями.

Расстояние

Структура Distance инкапсулирует расстояние, хранящееся как значение double, которое представляет расстояние в метрах. Эта структура определяет три доступные только для чтения свойства.

  • Kilometersтипа double, который представляет расстояние в километрах, охватываемых Distance.
  • Metersтипа double, который представляет расстояние в метрах, охватываемое Distance.
  • Milesтипа double, который представляет расстояние в милях, охватываемых Distance.

Distance объекты можно создать с помощью конструктора Distance, который требует аргумента метров, заданного как double:

Distance distance = new Distance(1450.5);

Кроме того, объекты Distance можно создавать с помощью методов фабрики FromKilometers, FromMeters, FromMilesи 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);

Штифты

Элемент управления Map позволяет помечать расположения объектами Pin. Pin — это маркер карты, который открывает окно сведений при нажатии:

снимок экрана значка карты и его информационного окна.

Когда объект Pin добавляется в коллекцию Map.Pins, значок отображается на карте.

Класс Pin имеет следующие свойства:

  • Addressтипа string, который обычно представляет адрес расположения пин-кода. Однако это может быть любое содержимое string, а не только адресом.
  • Labelтипа string, который обычно представляет заголовок пин-кода.
  • Locationтипа Location, который представляет широту и долготу пин-кода.
  • Typeтипа PinType, который представляет тип вывода.

Эти свойства поддерживаются объектами BindableProperty, что означает, что Pin может быть целью привязки данных. Дополнительные сведения об объектах привязки данных Pin см. раздел Отображение коллекции закреплений.

Кроме того, класс Pin определяет события MarkerClicked и InfoWindowClicked. Событие MarkerClicked запускается при нажатии пин-кода и событие InfoWindowClicked запускается при нажатии окна информации. Объект PinClickedEventArgs, который сопровождает оба события, имеет одно свойство HideInfoWindow типа bool.

Отображение пин-кода

Pin можно добавить в Map в 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>

Этот XAML создает объект Map, показывающий регион, заданный объектом MapSpan. Объект MapSpan сосредоточен на широте и долготе, представленных объектом Location, который охватывает диапазон 0,01 градуса широты и долготы. Объект Pin добавляется в коллекцию Map.Pins и рисуется на Map в расположении, указанном свойством Location. Сведения о классе Location см. в разделе Расположение и расстояние. Сведения о передаче аргументов в XAML в объекты, которые не имеют конструкторов по умолчанию, см. в статье Передавать аргументы в XAML.

Эквивалентный код C#:

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);

Этот пример кода отображает одну метку на карте.

снимок экрана с меткой на карте.

Взаимодействие с пином

По умолчанию при нажатии Pin отображается информационное окно.

снимок экрана значка на карте и соответствующего ему окна сведений.

Касание в другом месте карты закрывает окно сведений.

Класс Pin определяет событие MarkerClicked, которое запускается при нажатии Pin. Для отображения окна сведений не требуется обрабатывать это событие. Вместо этого это событие должно обрабатываться, когда требуется уведомить о том, что определенный пин-код был нажат.

Класс Pin также определяет событие InfoWindowClicked, которое запускается при нажатии окна информации. Это событие должно обрабатываться, когда необходимо уведомить о том, что коснулись конкретного окна со сведениями.

В следующем коде показан пример обработки этих событий:

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");
};

Объект PinClickedEventArgs, который сопровождает оба события, имеет одно свойство HideInfoWindow типа bool. Если для этого свойства задано значение true внутри обработчика событий, окно сведений будет скрыто.

Типы штырей

Объекты Pin включают свойство Type типа PinType, представляющее тип штыка. Перечисление PinType определяет следующие элементы:

  • Genericпредставляет универсальный пин-код.
  • Place, представляет пин-код для места.
  • SavedPinпредставляет пин-код для сохраненного расположения.
  • SearchResultпредставляет пин-код для результата поиска.

Однако установка свойства Pin.Type на любого участника PinType не изменяет внешний вид отрисованного значка. Вместо этого необходимо настроить обработчик Pin для изменения внешнего вида пинов. Дополнительные сведения о настройке обработчика см. в разделе Настройка элементов управления с помощью обработчиков.

Отображение коллекции значков

Класс Map определяет следующие привязываемые свойства:

  • ItemsSourceтипа IEnumerable, который указывает коллекцию элементов для отображения закреплений IEnumerable.
  • ItemTemplateтипа DataTemplate, который задает DataTemplate для применения к каждому элементу коллекции отображаемых значков.
  • ItemTemplateSelectorтипа DataTemplateSelector, который указывает DataTemplateSelector, который будет использоваться для выбора DataTemplate для пин-кода во время выполнения.

Важный

Свойство ItemTemplate имеет приоритет, если заданы свойства ItemTemplate и ItemTemplateSelector.

Map можно заполнить элементами, используя привязку данных для связи его свойства ItemsSource с коллекцией 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>

Данные свойства ItemsSource привязываются к свойству Positions подключенного модуля представления, который возвращает ObservableCollection объектов Position, который является пользовательским типом. Каждый объект Position определяет свойства Address и Description типа string, а также свойство Location типа Location.

Внешний вид каждого элемента в коллекции IEnumerable определяется путем задания свойства ItemTemplateDataTemplate, содержащего объект Pin, который привязывает данные к соответствующим свойствам.

На следующем снимку экрана показана Map, отображающая коллекцию Pin с помощью привязки данных:

снимок экрана карты с метками, связанными с данными.

Выбор внешнего вида элемента во время выполнения

Внешний вид каждого элемента в коллекции IEnumerable можно выбрать во время выполнения на основе значения элемента, задав для свойства ItemTemplateSelector значение 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>

В следующем примере показан класс 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;
    }
}

Класс MapItemTemplateSelector определяет свойства DefaultTemplate и SanFranTemplateDataTemplate, которые задаются различными шаблонами данных. Метод OnSelectTemplate возвращает SanFranTemplate, который отображает "Xamarin" в виде метки при нажатии Pin, когда элемент содержит адрес, содержащий "Сан-Франциско". Если элемент не содержит адрес, содержащий "Сан-Франциско", метод OnSelectTemplate возвращает DefaultTemplate.

Заметка

Вариант использования этой функции — привязка свойств подклассированных Pin объектов к разным свойствам на основе подтипа Pin.

Дополнительные сведения о селекторах шаблонов данных см. в разделе "Создание DataTemplateSelector".

Многоугольники, полилайны и круги

Polygon, Polylineи элементы Circle позволяют выделить определенные области на карте. Polygon — это фигура с полностью замкнутым контуром, которая может иметь цвет обводки и заливки. Polyline — это линия, которая не полностью ограничивает область. Circle выделяет круговую область карты:

Многоугольник и многоугольник на карте. Круг на карте.

Классы Polygon, Polylineи Circle являются производными от класса MapElement, который предоставляет следующие привязываемые свойства:

  • StrokeColor — это объект Color, определяющий цвет линии.
  • StrokeWidth — это объект float, определяющий ширину линии.

Класс Polygon определяет дополнительное привязываемое свойство:

  • FillColor — это объект Color, определяющий цвет фона многоугольника.

Кроме того, классы Polygon и Polyline определяют свойство GeoPath, которое представляет собой список объектов Location, указывающих точки фигуры.

Класс Circle определяет следующие привязываемые свойства:

  • Center — это объект Location, определяющий центр круга в широте и долготе.
  • Radius — это объект Distance, определяющий радиус круга в метрах, километрах или милях.
  • FillColor — это свойство Color, определяющее цвет в периметре круга.

Создание многоугольника

Объект Polygon можно добавить на карту, создав его и добавив его в коллекцию MapElements карты:

<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>

Эквивалентный код C#:

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);

Свойства StrokeColor и StrokeWidth указываются для задания структуры многоугольника. В этом примере значение свойства FillColor соответствует значению свойства StrokeColor, но имеет альфа-значение, указанное для прозрачности, что позволяет базовой карте отображаться через фигуру. Свойство GeoPath содержит список объектов Location, определяющих географические координаты точек многоугольника. Объект Polygon отображается на карте после добавления в коллекцию MapElementsMap.

Заметка

Polygon — это полностью заключенная фигура. Первые и последние точки будут автоматически соединены, если они не совпадают.

Создание полилайна

Объект Polyline можно добавить на карту, создав его и добавив его в коллекцию MapElements карты:

<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>

Эквивалентный код C#:

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);

Свойства StrokeColor и StrokeWidth указываются для задания внешнего вида строки. Свойство GeoPath содержит список объектов Location, определяющих географические координаты точек полилайна. Объект Polyline отображается на карте после того, как его добавили в коллекцию MapElements системы Map.

Создание круга

Объект Circle можно добавить на карту, создав его и добавив его в коллекцию MapElements карты:

<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>

Эквивалентный код C#:

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);

Расположение Circle на карте определяется значением свойств Center и Radius. Свойство Center определяет центр круга в широте и долготе, а свойство Radius определяет радиус круга в метрах. Свойства StrokeColor и StrokeWidth указываются для задания контура круга. Значение свойства FillColor указывает цвет в периметре круга. В этом примере оба значения цвета указывают альфа-канал, что позволяет базовой карте отображаться через круг. Объект Circle отображается на карте после того, как он был добавлен в коллекцию MapElements объекта Map.

Заметка

Класс GeographyUtils имеет метод расширения ToCircumferencePositions, который преобразует объект Circle (который определяет значения свойств Center и Radius) в список Location объектов, составляющих координаты широты и долготы периметра круга.

Геокодирование и геолокация

Класс Geocoding в пространстве имен Microsoft.Maui.Devices.Sensors можно использовать для геокодирования метки в позиционные координаты и обратного геокодирования координат в метку. См. для получения дополнительной информации по геокодированию.

Класс Geolocation в пространстве имен Microsoft.Maui.Devices.Sensors можно использовать для получения текущих координат географического расположения устройства. Дополнительные сведения см. в о геолокации.

Запуск собственного приложения карты

Собственное приложение карты на каждой платформе можно запустить из приложения .NET MAUI с помощью класса Launcher. Этот класс позволяет приложению открывать другое приложение с помощью пользовательской схемы URI. Функции средства запуска можно вызвать с помощью метода OpenAsync, передавая string или Uri аргумент, представляющий пользовательскую схему URL-адресов для открытия. Дополнительные сведения о классе Launcher см. в разделе Launcher.

Заметка

Альтернативой использованию класса Launcher является использование класса Map из пространства имен Microsoft.Maui.ApplicationModel. Дополнительные сведения см. в разделе Map.

Приложение карт на каждой платформе использует уникальную настраиваемую схему URI. Сведения о схеме URI для карт в iOS см. в секции Ссылки на карты на сайте developer.apple.com. Сведения о схеме URI карт для Android см. в руководстве разработчика карт и интенты Google Maps для Android на сайте developers.android.com. Сведения о схеме URI карт в Windows см. в разделе Запуск приложения "Карты Windows".

Открыть приложение карты в определенной точке

Расположение в приложении собственных карт можно открыть, добавив соответствующие параметры запроса в настраиваемую схему URI для каждого приложения карты:

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");
}

В этом примере код приводит к запуску стандартного приложения карт на каждой платформе, при этом карта центрируется на метке, представляющей указанное местоположение.

Запуск приложения карты с указаниями

Приложение собственных карт можно запустить, отображая направления, добавив соответствующие параметры запроса в настраиваемую схему URI для каждого приложения карты:

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");
}

Этот пример кода приводит к запуску встроенного приложения карты на каждой платформе, с картой, центрированной на маршруте между указанными местоположениями.