Сводка по главе 28. Расположение и карты

Примечание.

Эта книга была опубликована весной 2016 года и с тех пор не обновлялась. Многое в этой книге остается ценным, но некоторые материалы устарели, а некоторые разделы перестали быть полностью верными или полными.

Xamarin.Forms поддерживает элемент Map, который наследует от View. Из-за специальных требований платформы, связанных с использованием карт, они реализуются в отдельной сборке Xamarin.Forms.Maps и используют другое пространство имен: Xamarin.Forms.Maps.

Географическая система координат

Географическая система координат определяет позиции на сфероиде (или близком к нему теле), например на нашей планете. Координаты включают угловые значения широты и долготы.

Большой круг equator (экватор) находится ровно посередине между двумя полюсами, через которые проходит воображаемая ось вращения Земли.

Параллели и широта

Угол отклонения от экватора к северу или к югу, измеряемый относительно центра земли, дает линии с одинаковым значением широты, которые называются параллелями. Значения широты изменяются в диапазоне от 0 градусов (на экваторе) до 90 градусов на северном и южном полюсах. Отклонение к северу от экватора принято считать положительным, а к югу — отрицательным.

Долгота и меридианы

Половины больших кругов, проведенные от северного до южного полюса, считаются линиями с одинаковым значением долготы и называются меридианами. Они отсчитываются от "нулевого меридиана", который проходит через Гринвич (Англия). По соглашению долготы к востоку от Прайм-Меридиана являются положительными значениями от 0 до 180 градусов, а долготы к западу от Прайм-Меридиана являются отрицательными значениями от 0 до –180 градусов.

Равнопромежуточная проекция

Любая плоская карта Земли имеет искажения. Если все линии параллелей и меридианов сделать прямыми, а равные различия значений широты и долготы будут соответствовать равным расстояниям на карте, мы получим равнопромежуточную проекцию. Такая карта искажает области возле полюсов, сильно растягивая их горизонтально.

Проекция Меркатора

В популярной проекции Меркатора сделана попытка компенсировать горизонтальное растяжение, одновременно растягивая эти области по вертикали. Это приводит к тому, что на карте все близкие к полюсам области выглядят намного больше, чем на самом деле, но зато для расположенных рядом областей неплохо сохраняются реальные соотношения.

Службы и плитки карт

Службы карт используют разновидность проекции Меркатора, именуемую Web Mercator. Службы карт предоставляют клиенту плитки растровых изображений для выбранного расположения и масштаба.

Получение расположения пользователя

Классы Xamarin.FormsMap не включают объект для получения географического расположения пользователя, но это часто желательно при работе с картами, поэтому служба зависимостей должна обрабатывать ее.

Примечание.

Вместо этого приложения Xamarin.Forms могут использовать класс Geolocation, входящий в Xamarin.Essentials.

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

Решение Xamarin.FormsBook.Platform содержит код для API отслеживания расположения. Структура GeographicLocation инкапсулирует широту и долготу. Интерфейс ILocationTracker определяет два метода для запуска и приостановки отслеживания расположения, а также событие, информирующее о доступности нового расположения.

Диспетчер расположения в iOS

В iOS ILocationTracker реализуется через класс LocationTracker, который использует CLLocationManager платформы iOS.

Диспетчер расположения в Android

В Android ILocationTracker реализуется через класс LocationTracker, который использует класс LocationManager платформы Android.

Геолокатор UWP

В UWP (универсальная платформа Windows) ILocationTracker реализуется через класс LocationTracker, который использует Geolocator платформы UWP.

Отображение расположения телефона

В примере WhereAmI по данным средства отслеживания расположения отображается расположения телефона: в текстовой форме и на равнопромежуточной карте.

Необходимые служебные данные

Чтобы пример WhereAmI мог использовать отслеживание расположения, требуются определенные служебные данные. Во-первых, все проекты в решении WhereAmI должны иметь ссылки на соответствующие проекты в Xamarin.FormsBook.Platform, а каждый проект WhereAmI должен вызывать метод Toolkit.Init.

Некоторые дополнительные служебные данные, зависящие от платформы, связаны с предоставлением разрешений на отслеживание расположения.

Разрешения на отслеживание расположения в iOS

На платформе iOS файл info.plist должен содержать элементы с текстом вопроса, который предлагает пользователю разрешить получение данных о расположении этого пользователя.

Разрешения на отслеживание расположения в Android

Приложения Android, которым требуется доступ к данным о расположении пользователя, должны иметь разрешение ACCESS_FILE_LOCATION в файле AndroidManifest.xml.

Разрешения на отслеживание расположения в UWP

Приложения UWP должны иметь возможность устройства location, отмеченную в файле Package.appxmanifest.

Работа с Xamarin.Forms.Maps

К использованию класса Map применяются сразу несколько требований.

Пакет NuGet

В решение приложения необходимо добавить библиотеку NuGet Xamarin.Forms.Maps. Номер версии должен быть таким же, как у установленного пакета Xamarin.Forms.

Инициализация пакета Maps

Проекты приложения должны вызывать метод Xamarin.FormsMaps.Init после вызова Xamarin.Forms.Forms.Init.

Включение служб карт

Поскольку Map может получать расположение пользователя, приложение должно получить разрешение пользователя, как описано выше в этой главе.

Включение карт в iOS

Чтобы использовать Map, приложение для iOS должно иметь две строки в файле info.plist.

Включение карт в Android

Чтобы использовать Карты Google, требуется ключ авторизации. Этот ключ помещается в файл AndroidManifest.xml. Кроме того, файл AndroidManifest.xml должен иметь теги manifest, которые участвуют в получении расположения пользователя.

Включение карт в UWP

Чтобы использовать Карты Bing, приложение UWP должно иметь ключ авторизации. Этот ключ передается в качестве аргумента в метод Xamarin.FormsMaps.Init. Кроме того, в приложении должно быть включено использование служб местоположения.

Неоформленная карта

Пример MapDemos состоит из файла MapsDemoHomePage.xaml и файла кода программной части MapsDemoHomePage.xaml.cs, который позволяет переходить к нескольким демонстрационным программам.

В файле BasicMapPage.xaml показано, как отобразить представление Map. По умолчанию отображается город Рим, но пользователь может управлять картой.

Чтобы отключить горизонтальную и вертикальную прокрутку, задайте для свойства HasScrollEnabled значение false. Чтобы отключить масштабирование, задайте для HasZoomEnabled значение false. Эти свойства могут работать не на всех платформах.

Улицы и ландшафт

Вы можете отображать разные типы карт, задавая свойство MapType объекта Map с типом MapType, которое представляет собой перечисление с тремя элементами:

В файле MapTypesPage.xaml показано, как использовать переключатель для выбора типа карты. Здесь используется класс RadioButtonManager из библиотеки Xamarin.FormsBook.Toolkit и класс на основе файла MapTypeRadioButton.xaml.

Координаты на карте

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

VisibleRegion имеет тип MapSpan, это класс с четырьмя свойствами только для чтения:

  • Center типа Position
  • LatitudeDegrees с типом double, обозначает высоту отображаемой на карте области;
  • LongitudeDegrees с типом double, обозначает ширину отображаемой на карте области;
  • Radius с типом Distance, обозначает размер максимально возможной области круглой формы на отображаемой части карты.

Position и Distance являются структурами. Position определяет два свойства только для чтения, которые можно задать с помощью конструктора Position.

Distance предоставляет независимую от единиц изменения информацию о расстоянии, конвертируя величины между метрической и имперской системами измерения. Значение Distance можно создать несколькими способами:

Это значение можно получить из трех свойств:

Файл MapCoordinatesPage.xaml содержит несколько элементов Label для отображения информации MapSpan. Файл кода программной части MapCoordinatesPage.xaml.cs использует таймер для обновления этой информации по мере того, как пользователь оперирует картой.

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

Впервые в этой книге упоминается библиотека Xamarin.FormsBook.Toolkit.Maps, которая содержит типы, зависящие от реализации карты, но не зависящие от платформы. Класс PositionExtensions имеет метод ToString для Position и другой метод для вычисления расстояния между двумя значениями Position.

Настройка исходного положения

Вы можете вызвать метод MoveToRegion из Map, чтобы программным образом задать расположение и уровень масштабирования на карте. Аргумент имеет тип MapSpan. Создать объект MapSpan можно двумя способами:

Кроме того, вы можете создать новый тип MapSpan из уже существующего, используя методы ClampLatitude и WithZoom.

Файл WyomingPage.xaml и файл кода программной части WyomingPage.xaml.cs демонстрируют применение метода MoveToRegion для отображения карты штата Вайоминг.

Для инициализации расположения на карте можно также применить конструктор Map с объектом MapSpan. Файл XamarinHQPage.xaml демонстрирует, как выполнить это на чистом XAML на примере карты офиса Xamarin в Сан-Франциско.

Динамическое масштабирование

С помощью Slider можно динамически масштабировать карту. Файл RadiusZoomPage.xaml и файл кода программной части RadiusZoomPage.xaml.cs демонстрируют, как изменить радиус карты на основе значения Slider.

Файл LongitudeZoomPage.xaml и файл кода программной части LongitudeZoomPage.xaml.cs демонстрируют альтернативный подход, который хорошо подходит для Android. К сожалению, ни один из этих подходов не подходит для платформ Windows.

Расположение телефона

Свойство IsShowingUser класса Map работает на разных платформах немного по-разному. Это видно из примера ShowLocationPage.xaml.

  • В iOS синяя точка обозначает расположение телефона, но к этому месту нужно перемещать карту вручную.
  • В Android отображается значок, при нажатии которого карта перемещается к текущему расположению телефона.
  • В UWP поведение похоже на iOS, но иногда карта автоматически перемещается к расположению телефона.

Проект MapDemos пытается имитировать подход, реализованный в Android, определяя кнопку со значком на основе файла MyLocationButton.xaml и файла кода программной части MyLocationButton.xaml.cs.

Файл GoToLocationPage.xaml и файл кода программной части GoToLocationPage.xaml.cs используют эту кнопку для перехода к расположению телефона.

Маркеры и научные музеи

Напоследок класс Map определяет свойство Pins с типом IList<Pin>. Класс Pin определяет четыре свойства:

  • Label с типом string, обязательное свойство;
  • Address с типом string, необязательный адрес в понятной для человека форме;
  • Position с типом Position, отображает расположение маркера на карте;
  • Type с типом PinType, перечисление, не используется.

Проект MapDemos содержит файл ScienceMuseums.xml, который перечисляет все научные музеи США, а также классы Locations и Site для десериализации этих данных.

Файл ScienceMuseumsPage.xaml и файл кода программной части ScienceMuseumsPage.xaml.cs отображают на карте маркеры, обозначающие эти научные музеи. Когда пользователь касается маркера, отображается адрес и веб-сайт соответствующего музея.

Расстояние между двумя точками

Класс PositionExtensions содержит метод DistanceTo с упрощенным методом расчета расстояния между двумя географическими точками.

Это используется в файле LocalMuseumsPage.xaml и файле кода программной части LocalMuseumsPage.xaml.cs для отображения расстояния между музеем и текущим расположением пользователя.

Три снимка экрана со страницей музеев на местности

Также эта программа демонстрирует, как динамически ограничивать количество маркеров в зависимости от расположения на карте.

Геокодирование и завершение работы

Сборка Xamarin.Forms.Карты также содержит Geocoder класс с методомGetPositionsForAddressAsync, который преобразует текстовый адрес в ноль или более возможные географические позиции, а другой методGetAddressesForPositionAsync, который преобразуется в другое направление.

Файл GeocoderRoundTrip.xaml и файл кода программной части GeocoderRoundTrip.xaml.cs демонстрируют применение этой возможности.