Сводка по главе 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
можно создать несколькими способами:
- конструктор
Distance
с расстоянием в метрах; - статический метод
Distance.FromMeters
; - статический метод
Distance.FromKilometers
; - статический метод
Distance.FromMiles
;
Это значение можно получить из трех свойств:
Meters
типаdouble
Kilometers
типаdouble
Miles
типаdouble
Файл MapCoordinatesPage.xaml содержит несколько элементов Label
для отображения информации MapSpan
. Файл кода программной части MapCoordinatesPage.xaml.cs использует таймер для обновления этой информации по мере того, как пользователь оперирует картой.
Расширения для определения положения
Впервые в этой книге упоминается библиотека Xamarin.FormsBook.Toolkit.Maps, которая содержит типы, зависящие от реализации карты, но не зависящие от платформы. Класс PositionExtensions
имеет метод ToString
для Position
и другой метод для вычисления расстояния между двумя значениями Position
.
Настройка исходного положения
Вы можете вызвать метод MoveToRegion
из Map
, чтобы программным образом задать расположение и уровень масштабирования на карте. Аргумент имеет тип MapSpan
. Создать объект MapSpan
можно двумя способами:
- использовать конструктор
MapSpan
сPosition
и диапазоном широты и долготы; - использовать
MapSpan.FromCenterAndRadius
сPosition
и радиусом.
Кроме того, вы можете создать новый тип 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 демонстрируют применение этой возможности.