Яндекс карты наклон карты как настроить
Перейти к содержимому

Яндекс карты наклон карты как настроить

  • автор:

Увеличение, перемещение, поворот или наклон карты в приложении «Карты» на Mac

В приложении «Карты» на Mac выполните любое из указанных действий.

  • Увеличение и уменьшение масштаба. Нажимайте кнопки увеличения и уменьшения ( и ) в нижнем правом углу карты. Чтобы видеть значение масштаба карты во время увеличения или уменьшения изображения, выберите меню «Вид» > «Показать масштаб карты». Масштаб отображается в левом верхнем углу.
  • Перемещение вверх, вниз, влево или вправо. Удерживая нажатой кнопку мыши или трекпада, перетяните карту. На трекпаде можно также перетягивать карту двумя пальцами.
  • Поворот карты. Удерживая нажатым указатель на компасе, перетягивайте его влево, вправо, вверх или вниз. После поворота карты можно вернуться к ориентации на север, нажав на компас или нажав сочетание клавиш Shift-Command-стрелка вверх.
  • Наклон карты. Нажмите кнопку «3D» в панели инструментов, затем перетяните бегунок в правом нижнем углу.
  • Просмотр в виде интерактивного трехмерного глобуса. Если у Вас Mac с чипом Apple, уменьшайте масштаб, пока карта не сменится глобусом. Чтобы повернуть глобус, потяните за него, или меняйте масштаб, чтобы изучать горные хребты, пустыни, океаны и другие объекты.

См. такжеНастройка оформления карты в приложении «Карты» на Mac

«Яндекс. Карты» перешли на вектор

Сегодня вышли новые версии мобильных приложений «Яндекс.Карты» для iOS и Android.

Самое главное нововведение, что карты всех регионов заметно уменьшились в размере. Например, офлайн-карта Москвы теперь занимает всего 144 МБ вместо 1,9 ГБ, офлайн-карта Санкт-Петербурга и области — 231 МБ вместо 3,2 ГБ.

Уменьшение размера достигнуто за счёт того, что «Яндекс» наконец-то перешёл с растровых карт на векторные, так что теперь не нужно сохранять несколько вариантов одной и той же карты в разных масштабах.

Кроме того, в новой версии карт реализован офлайновый поиск — то, о чём давно просили пользователи. На картах без подключения к интернету можно искать адреса и организации: кафе, магазины, банкоматы, аптеки, АЗС и проч. Карты покажут расписание транспорта, адрес организации и сообщат подробности: время работы и телефон. Для гостиниц указана примерная стоимость номеров, для ресторанов — средний чек.

Разработчики пишут, что добавили ещё несколько функций: во-первых, изменение угла наклона карты (нужно провести двумя пальцами по экрану), во-вторых, постоянное отображение на видном месте названий улиц, даже если включен режим пробок или проложен маршрут.

  • Яндекс.Карты
  • векторная графика
  • средний чек

Yandex MapKit для новичков: разрабатываем карты в Android-приложении

Yandex MapKit — это кроссплатформенная библиотека, позволяющая использовать картографические данные и технологии Яндекса в мобильных приложениях. Список доступных возможностей действительно впечатляет, но разработчику, впервые столкнувшемуся с необходимостью работать с Яндекс-картами, многое может показаться непонятным и неочевидным в использовании.

Поэтому, чтобы научиться применять полезные особенности MapKit’a, мы с вами напишем небольшое приложение, в которое внедрим и настроим данную библиотеку: откроем определённую область на карте; выставим метку в нужном месте; установим на неё желаемые растровые и векторные изображения; поиграемся с зумом; обработаем нажатие на пин; а также будем при клике визуально выделять объекты на карте и получать от них интересующую нас информацию.

1) Введение: внедрение и настройка Yandex MapKit в проекте

Чтобы создать и запустить приложение с Яндекс-картами, первым делом необходимо:

  • Получить ключ;
  • Установить библиотеку MapKit;
  • Настроить библиотеку;
  • Собрать и запустить приложение.

Эти пункты весьма понятно и доступно описаны в документации. Дабы не копировать информацию, читателям предлагается самим ознакомиться, повторить данные шаги и затем запустить приложение с Яндекс-картой. Отметим, что в нашем приложении мы будем использовать полную full-версию библиотеки (на момент написания статьи — версия 4.3.1-full), а писать код на языке Kotlin, используя View Binding.

Отметим несколько важных моментов:

  • Какими знаниями вы должны обладать: Kotlin базовый уровень; умение собрать проект, запустить приложение на эмуляторе или телефоне, загрузить необходимые библиотеки; View Binding.
  • Ознакомьтесь с условиями использования MapKit. Так, например, нельзя скрывать логотип Яндекса на карте за другими объектами. Также, в вашем приложении в разделе «о программе» должна быть ссылка на условия использования Яндекс-карт.
  • API-ключ должен быть задан единожды перед инициализацией MapKitFactory. Хорошим тоном будет задать ключ при запуске приложения в методе Application.onCreate() , а инициализировать уже в других необходимых активити и фрагментах. Если же при каких-то условиях будет повторно вызван MapKitFactory.setApiKey(«Ваш API-ключ»), вы получите краш приложения и ошибку в логах: «java.lang.AssertionError: You need to set the API key before using MapKit!». Примером появления подобной ошибки может быть следующий сценарий: переход с одного экрана во фрагмент с Яндекс-картами, где мы задаём API-ключ (карта при этом откроется и будет адекватно работать) -> возвращаемся на предыдущий экран -> вновь открываем фрагмент с картами -> происходит краш приложения.
  • Допущения в данном проекте: в случае, если по каким-то причинам (как, например, в нашем приложении), логика работы карт и API-ключ находятся в одном активити/фрагменте, раздувать макет необходимо только после того, как установлен API-ключ. Иначе, проявится ошибка, указанная в предыдущем пункте. Также необходимо учесть момент пересоздания активити/фрагмента, например, для случая изменения ориентации экрана, вследствие чего вновь будет вызван метод MapKitFactory.setApiKey(«Ваш API-ключ»). Воспользуемся проверкой: установили ли мы ранее API-ключ для Яндекс-карт. Для этого сохраним данную информацию:
override fun onSaveInstanceState(outState: Bundle)

А при создании активности, в методе onCreate будем проверять, был ли уже установлен API-ключ ранее при помощи функции setApiKey:

private fun setApiKey(savedInstanceState: Bundle?) < val haveApiKey = savedInstanceState?.getBoolean("haveApiKey") ?: false // При первом запуске приложения всегда false if (!haveApiKey) < MapKitFactory.setApiKey(MAPKIT_API_KEY)>> // API-ключ должен быть задан единожды перед инициализацией MapKitFactory 

Что же, надеюсь, у вас получилось собрать проект со своей первой Яндекс-картой и перед вами на экране отобразились материки, моря да океаны:

Земля в иллюминаторе, Земля в иллюминаторе, Земля в иллюминаторе видна.

А код выглядит примерно следующим образом:

class MainActivity : AppCompatActivity() < private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) < super.onCreate(savedInstanceState) setApiKey(savedInstanceState) // Проверяем: был ли уже ранее установлен API-ключ в приложении. Если нет - устанавливаем его. MapKitFactory.initialize(this) // Инициализация библиотеки для загрузки необходимых нативных библиотек. binding = ActivityMainBinding.inflate(layoutInflater) // Раздуваем макет только после того, как установили API-ключ setContentView(binding.root) // Размещаем пользовательский интерфейс в экране активности >private fun setApiKey(savedInstanceState: Bundle?) < val haveApiKey = savedInstanceState?.getBoolean("haveApiKey") ?: false // При первом запуске приложения всегда false if (!haveApiKey) < MapKitFactory.setApiKey(MAPKIT_API_KEY) // API-ключ должен быть задан единожды перед инициализацией MapKitFactory >> // Если Activity уничтожается (например, при нехватке памяти или при повороте экрана) - сохраняем информацию, что API-ключ уже был получен ранее override fun onSaveInstanceState(outState: Bundle) < super.onSaveInstanceState(outState) outState.putBoolean("haveApiKey", true) >// Отображаем карты перед моментом, когда активити с картой станет видимой пользователю: override fun onStart() < super.onStart() MapKitFactory.getInstance().onStart() binding.mapview.onStart() >// Останавливаем обработку карты, когда активити с картой становится невидимым для пользователя: override fun onStop() < binding.mapview.onStop() MapKitFactory.getInstance().onStop() super.onStop() >companion object < const val MAPKIT_API_KEY = "Ваш API-ключ" >>

Соответствующая разметка .xml:

Теперь, когда все готово, перейдём к ещё более интересным и полезным моментам – интерактивам с картой. Пример полного кода будет приведён в конце статьи, а также его можно найти в GitHub.

2) Открываем определённую область на карте

Первым делом сделаем так, чтобы при открытии карты нам сразу показывалась определённая область. Здесь и далее, при необходимости импорта, выбираем библиотеку Яндекса. Добавим новые переменные: startLocation – точку, содержащую координаты (широту и долготу), в которую должна переместиться камера и zoomValue – величину приближения к данной точке:

private val startLocation = Point(59.9402, 30.315) private var zoomValue: Float = 16.5f

Создадим функцию moveToStartLocation() , в которой у нашей mapview для карты вызовем метод, перемещающий камеру к необходимой позиции:

private fun moveToStartLocation()

Конструктор класса CameraPosition принимает, соответственно: точку с координатами, величину необходимого приближения, азимут и наклон (наклон камеры в градусах, добавляет визуально ощущение 3d). Максимальное возможное значение зума – 21.0f, минимальное – 0.0f. Также можем вызвать перегруженный метод move, чтобы перемещение в нужную область происходило красиво со стартовой анимацией:

binding.mapview.map.move( CameraPosition(startLocation, zoomValue, 0.0f, 0.0f), Animation(SMOOTH, 5f), null)

Здесь, помимо CameraPosition, дополнительно необходимо указать параметры анимации (которая зависит от типа animationType и длительности duration) и функцию CameraCallback , которая принимает логический аргумент, обозначающий завершение действия камеры. Если движение камеры по каким-то причинам прерывается, то в качестве аргумента передаётся «false»; если движение камеры завершилось успешно – «true». CameraCallback имеет необязательный тип, т.е. может быть не инициализирован – укажем здесь null.

Не забываем вызвать moveToStartLocation() в методе onCreate – и можем проверять работу перемещения камеры на стартовую локацию:

У моря над вольной Невой раскинулся каменный град - дворцов и соборов парад!

3) Устанавливаем метку на карте

Отметим нашу стартовую точку пином. Для начала загрузим в проект иконку с расширением png – скачайте файл ic_pin_png и перетащите его в папку drawable проекта.

Заранее создадим две переменные, которые проинициализируем и о которых более подробно расскажем далее:

private lateinit var mapObjectCollection: MapObjectCollection private lateinit var placemarkMapObject: PlacemarkMapObject

Реализуем функцию setMarkerInStartLocation() , отвечающую за установку метки на карте. В ней первым делом создаём ссылку на нашу картинку — marker. Затем инициализируем коллекцию различных возможных объектов на карте mapObjectCollection, которая может содержать любой набор элементов MapObject. MapObject – это пользовательский объект, отображаемый на карте, например, метка с иконкой или геометрическая фигура. Создадим такой геопозиционированный объект PlacemarkMapObject , являющийся наследником MapObject – метку с иконкой — который будет располагаться по координате, используемой ранее.

Для этого к mapObjectCollection применим метод addPlacemark , в котором укажем необходимую точку с координатами и, с помощью класса ImageProvider , ссылку на иконку. Таким образом мы создадим новую метку с нашим изображением и добавим её в текущую коллекцию. Если указать только точку с координатами, тогда получится пин со значком и стилем по умолчанию (будет выглядеть, как обычная точка на карте).

Дополнительно, к placemarkMapObject мы можем применить различные свойства, например, установить прозрачность метки и текст сверху в придачу при помощи команд setOpacity и setText соответственно. В итоге, произведя все вышеперечисленные действия, мы имеем следующую функцию:

private fun setMarkerInStartLocation() < val marker = R.drawable.ic_pin_black_png // Добавляем ссылку на картинку mapObjectCollection = binding.mapview.map.mapObjects // Инициализируем коллекцию различных объектов на карте placemarkMapObject = mapObjectCollection.addPlacemark(startLocation, ImageProvider.fromResource(this, marker)) // Добавляем метку со значком placemarkMapObject.opacity = 0.5f // Устанавливаем прозрачность метке placemarkMapObject.setText("Обязательно к посещению!") // Устанавливаем текст сверху метки >

Вызываем setMarkerFirstOpen() в onCreate, запускаем приложение и наблюдаем метку над Эрмитажем.

Вот он - один из крупнейших в мире художественных и культурно-исторических музеев.

4) Использование векторных изображений

Обычно мы используем не png файлы, а векторные изображения. Тут имеется одна неприятная особенность: векторные изображения в качестве маркеров в MapKit не поддерживаются – они просто не будут отображаться. Но данный момент можно обойти. ImageProvider умеет работать с bitmap. Таким образом, нам стоит просто перевести векторное изображение в bitmap и использовать по назначению. Для этого создадим соответствующую функцию:

private fun createBitmapFromVector(art: Int): Bitmap?

Используем её: загрузите приложенные векторные изображения ic_pin_black_svg, ic_pin_blue_svg и ic_pin_red_svg. Затем добавьте их в свой проект: правой кнопкой по папке drawable -> Vector Asset -> Local file -> установите размер 64dp X 64dp -> Finish.

После этого в функции setMarkerInStartLocation() исправим marker и placemarkMapObject на:

val marker = createBitmapFromVector(R.drawable.ic_pin_black_svg) placemarkMapObject = mapObjectCollection.addPlacemark(startLocation, ImageProvider.fromBitmap(marker))

Таким образом мы можем использовать в качестве иконок для меток и векторные и растровые изображения.

5) Работа с зумом: меняем иконку маркера при отдалении и приближении камеры

Теперь обработаем моменты увеличения и уменьшения масштаба карты пользователем: пусть при пересечении некоторой границы величины зума маркер становится красным при отдалении камеры и синим при приближении. Данную величину границы зума сразу вынесем в константу в companion object:

const val ZOOM_BOUNDARY = 16.4f

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

class MainActivity : AppCompatActivity(), CameraListener 

и переопределяем метод onCameraPositionChanged , который срабатывает при изменении положения камеры:

override fun onCameraPositionChanged( map: Map, cameraPosition: CameraPosition, cameraUpdateReason: CameraUpdateReason, finished: Boolean ) <>

Здесь параметрами являются:

  • map - новая область карты (будьте внимательны при импорте – это не коллекция Map);
  • cameraPosition - текущее положение камеры;
  • cameraUpdateReason - причина обновления камеры. Это enum-класс, включающий в себя две константы: APPLICATION – т.е. причиной обновления камеры является вызов приложением метода move; GESTURES – причиной являются действия пользователя, такие как масштабирование, поворот и прочее;
  • finished – завершилось ли движение камеры окончательно. Будет «true», если камера закончила движение, «false» - в противном случае.

Обсудим логику работы изменения иконки метки при регулировании масштаба отображения карты. После того как пользователь успешно приблизил или отдалил карту, т.е. finished==true, проверим величину нового зума. Если величина зума cameraPosition.zoom будет меньше фиксированного значения ZOOM_BOUNDARY - мы поменяем изображение метки на красную иконку. Иначе, будет установлен пин синего цвета. Так же, чтобы каждый раз не производить излишнюю замену иконки при изменении масштаба пользователем, когда порог ZOOM_BOUNDARY не был преодолён, добавим дополнительную проверку: стала ли новая величина зума больше или меньше фиксированного значения? Для этого будем перезаписывать значение zoomValue после каждого изменения масштаба карты пользователем. В итоге имеем:

override fun onCameraPositionChanged( map: Map, cameraPosition: CameraPosition, cameraUpdateReason: CameraUpdateReason, finished: Boolean ) < if (finished) < // Если камера закончила движение when < cameraPosition.zoom >= ZOOM_BOUNDARY && zoomValue  < placemarkMapObject.setIcon(ImageProvider.fromBitmap(createBitmapFromVector(R.drawable.ic_pin_blue_svg))) >cameraPosition.zoom = ZOOM_BOUNDARY -> < placemarkMapObject.setIcon(ImageProvider.fromBitmap(createBitmapFromVector(R.drawable.ic_pin_red_svg))) >> zoomValue = cameraPosition.zoom // После изменения позиции камеры сохраняем величину зума > >

И последний штрих: необходимо инициализировать метод слушателя камеры, чтобы логика, прописанная в onCameraPositionChanged , срабатывала. В onCreate добавляем следующую команду и после проверяем в приложении изменение иконки метки при регулировании масштаба:

binding.mapview.map.addCameraListener(this)

Далековато будет! А так уже и рассмотреть все можно в мельчайших деталях

6) Обработка события нажатия на метку

Перейдем к обработке события нажатия на пин – выведем всплывающее окно Toast с надписью.

Для этого нам понадобится интерфейс MapObjectTapListener, как раз отвечающий за тапы по различным объектам на карте. Создадим экземпляр класса MapObjectTapListener и переопределим onMapObjectTap, который возвращает «true», если событие было обработано, иначе – «false». При этом, мы можем использовать информацию о mapObject’е и точке с координатами, по которой произошёл тап. Мы же просто воспользуемся Toast’ом с фиксированным текстом:

private val mapObjectTapListener = object : MapObjectTapListener < override fun onMapObjectTap(mapObject: MapObject, point: Point): Boolean< Toast.makeText(applicationContext, "Эрмитаж — музей изобразительных искусств", Toast.LENGTH_SHORT).show() return true >>

Интерфейс MapObjectTapListener может быть присоединён к любому MapObject’у. Подключим этот слушатель в функции setMarkerFirstOpen() к нашей метке placemarkMapObject :

placemarkMapObject.addTapListener(mapObjectTapListener)

Готово! Теперь, при тапе на метку, будет появляться всплывающее окно с необходимой информацией.

Осведомлён - значит вооружён!

Отдельно отметим, почему мы создаем отдельную переменную mapObjectTapListener , а не сразу пишем в функции setMarkerFirstOpen подобным образом:

placemarkMapObject.addTapListener(object : MapObjectTapListener < override fun onMapObjectTap(mapObject: MapObject, point: Point): Boolean< Toast.makeText(applicationContext, "Эрмитаж — музей изобразительных искусств", Toast.LENGTH_SHORT).show() return true>>)

Дело в том, что MapKit хранит слабые ссылки на передаваемые ему Listener-объекты, поэтому их необходимо сохранять на стороне приложения. Иначе, первое время клики будут работать адекватно, а затем перестанут реагировать на тапы. Это связано с тем, что сборщик мусора, который не учитывает связь ссылки и объекта в куче при выявлении объектов, подлежащих удалению, в какой-то момент удалит наш слушатель. После этого при тапе на пин в логах возникнет неприятное сообщение: «yandex.maps.runtime: Java object is already finalized. Nothing to do» и клики перестанут обрабатываться должным образом. Поэтому, необходимо использовать строгую ссылку на объект MapObjectTapListener, что мы и делаем выше.

Бонусные разделы

Весьма полезной и интересной темой в Mapkit является получения информации об объекте, используя поиск и метаданные. Поскольку наш туториал рассчитан на новичков, сейчас мы не будем подробно разбираться в том, как именно устроен поиск и как работать с метаданными в mapkit. Но, в качестве дополнительной полезной информации, без особой конкретики и не раскрывая темы в полном объёме, приведём примеры кода с использованием этих моментов в пунктах 7*) и 8*). Более подробно прочитать о данных возможностях Mapkit можно в статье «Поиск в MapKit: Tips & Tricks».

7) Выделение объекта на карте

Продолжим знакомство со слушателями объектов на карте. Теперь будем работать с GeoObject – объектом в слоях карты, примером которого может выступать здание или памятник. Слушателем будет выступать экземпляр класса GeoObjectTapListener, в котором требуется переопределить onObjectTap. Метод onObjectTap позволяет извлечь краткую информацию затронутого геообъекта и возвращает булевское значение. Так, если мы вернём «false» – тогда событие клика распространится на карту, и его сможет перехватить другой слушатель. Если «true» – «дальше» событие никуда не пойдёт. Пример: если пользователь клацает на объект, а в проекте имеется дополнительный слушатель, обрабатывающий действия по всей карте (как, например, в пункте 8), то при значении «true» для onObjectTap данное событие более перехвачено не будет.

Давайте подсветим какое-либо здание при тапе на него, иначе говоря, отобразим для пользователя «выделение» объекта. Для этого нам понадобятся идентификаторы объекта и слоя. Получим геообъект из geoObjectTapEvent методом getGeoObject. Информация про геообъект хранится в метаданных. Метаданные бывают разных видов, более подробно можно ознакомиться в «Поиск в MapKit: Tips & Tricks». Доступ к информации можно получить с помощью метода getMetadataContainer(), для которого с помощью метода getItem указываем ключ для этого контейнера - тип необходимых метаданных. У нас данный ключ – GeoObjectSelectionMetadata.

После того как мы получили метаданные, для карты mapview используем метод selectGeoObject, в который передаем необходимые идентификаторы объекта и слоя:

private val tapListener = object : GeoObjectTapListener < override fun onObjectTap(geoObjectTapEvent: GeoObjectTapEvent): Boolean < val selectionMetadata: GeoObjectSelectionMetadata = geoObjectTapEvent .geoObject .metadataContainer .getItem(GeoObjectSelectionMetadata::class.java) binding.mapview.map.selectGeoObject(selectionMetadata.id, selectionMetadata.layerId) return false >>

Подключаем данный слушатель:

binding.mapview.map.addTapListener(tapListener) // Добавляем карте слушатель тапов по объектам

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

Ага, теперь я тебя точно не потеряю из виду!

8) Получаем информацию об объекте при тапе на него

Осуществим следующую идею: при тапе в любую область карты будет появляться всплывающее окно с информацией об улице в данном месте. Если по каким-то причинам улицы нет, например, если тапнули по реке или не пришел ответ от сервера – будем выводить соответствующее сообщение.

В переопределённой функции onSearchResponse, последовательно используя различные вызовы, мы сможем докопаться до интересующей нас сущности – будь то улица, дом, маршрут, страна и прочее. А данную информацию можем использовать уже как угодно, например, поместить в Toast:

private val searchListener = object : Session.SearchListener < override fun onSearchResponse(response: Response) < val street = response.collection.children.firstOrNull()?.obj ?.metadataContainer ?.getItem(ToponymObjectMetadata::class.java) ?.address ?.components ?.firstOrNull < it.kinds.contains(Address.Component.Kind.STREET)>?.name ?: "Информация об улице не найдена" Toast.makeText(applicationContext, street, Toast.LENGTH_SHORT).show() > override fun onSearchError(p0: Error) < >>

Предварительно создадим две новые переменные: поисковую сессию searchSession и интерфейс для начала поиска searchManager, которые проинициализируем далее:

lateinit var searchManager: SearchManager lateinit var searchSession: Session

Теперь searchListener надо поместить в другой слушатель – inputListener, который обрабатывает тапы по всей карте. В нем переопределяются два метода – короткое и длинное нажатие. onMapTap - вызывается при быстром касании, если оно не было обработано геообъектами или объектами карты. Как уже говорилось ранее в пункте 7: если касание было обработано onObjectTap, то onMapTap может не сработать. Чтобы метод адекватно обработал тап – в onObjectTap необходимо вернуть «false». В самом методе onMapTap инициализируем поисковую сессию searchSession:

private val inputListener = object : InputListener < override fun onMapTap(map: Map, point: Point) < searchSession = searchManager.submit(point, 20, SearchOptions(), searchListener) >override fun onMapLongTap(map: Map, point: Point) <> >

Метод обратного поиска submit требует на вход точку с координатами, величину зума (в окрестности которой будет происходить поиск), настройки поиска и слушатель.

После, в методе onCreate инициализируем searchManager и добавляем к нашей карте слушатель тапов по карте с извлечением информации:

searchManager = SearchFactory.getInstance().createSearchManager(SearchManagerType.ONLINE) binding.mapview.map.addInputListener(inputListener) // Добавляем слушатель тапов по карте с извлечением информации

В итоге, после проведенных манипуляций, при клике на какое-либо место в городе на экране будет появляться название соответствующей улицы:

Окей, Яндекс, а где тут самые вкусные пышки, не подскажешь?

Заключение

Yandex MapKit предоставляет гигантское количество возможностей, с помощью которых можно реализовать самые различные интересные и полезные идеи. Сегодня мы познакомились с основными моментами использования Яндекс-карт: были показаны часто используемые методы, даны различные рекомендации и хитрости для проблемных мест, ответы на вероятно возникающие вопросы при первом знакомстве с данной библиотекой.

Данная статья не является исчерпывающей, наоборот - с помощью Yandex MapKit’а можно решить множество разнообразных задач: построить маршрут для пешей прогулки иль поездки на общественном транспорте; отобразить на карте ближайший к пользователю банкомат; найти нужную организацию; узнать о пробках на дорогах в реальном времени; предоставить местоположение пользователя; использовать панорамы; получить какую-либо информацию об объекте на карте и многое, многое другое.

Дополнительно ознакомиться с примерами реализации части функционала можно здесь.

Искренне надеюсь, что полученные сегодня знания ускорили ваш порог вхождения в Яндекс MapKit, дали понимание, каким образом можно взаимодействовать и работать с Яндекс-картами в плане разработки.

Дерзайте! И помните: «Дорогу осилит идущий».

Список используемой литературы:

  • Руководство MapKit;
  • Условия использования MapKit;
  • Статья «Поиск в MapKit: Tips & Tricks»;
  • Примеры некоторых возможностей Mapkit;
  • Проект на Github.

Код программы

Код программы

class MainActivity : AppCompatActivity(), CameraListener < private lateinit var binding: ActivityMainBinding private lateinit var mapObjectCollection: MapObjectCollection // Коллекция различных объектов на карте private lateinit var placemarkMapObject: PlacemarkMapObject // Геопозиционированный объект (метка со значком) на карте private val startLocation = Point(59.9402, 30.315) // Координаты Эрмитажа private var zoomValue: Float = 16.5f // Величина зума lateinit var searchManager: SearchManager lateinit var searchSession: Session private val mapObjectTapListener = object : MapObjectTapListener < override fun onMapObjectTap(mapObject: MapObject, point: Point): Boolean < Toast.makeText(applicationContext, "Эрмитаж — музей изобразительных искусств", Toast.LENGTH_SHORT).show() return true >> private val geoObjectTapListener = object : GeoObjectTapListener < override fun onObjectTap(geoObjectTapEvent: GeoObjectTapEvent): Boolean < val selectionMetadata: GeoObjectSelectionMetadata = geoObjectTapEvent .geoObject .metadataContainer .getItem(GeoObjectSelectionMetadata::class.java) binding.mapview.map.selectGeoObject(selectionMetadata.id, selectionMetadata.layerId) return false >> private val searchListener = object : Session.SearchListener < override fun onSearchResponse(response: Response) < val street = response.collection.children.firstOrNull()?.obj ?.metadataContainer ?.getItem(ToponymObjectMetadata::class.java) ?.address ?.components ?.firstOrNull < it.kinds.contains(Address.Component.Kind.STREET) >?.name ?: "Информация об улице не найдена" Toast.makeText(applicationContext, street, Toast.LENGTH_SHORT).show() > override fun onSearchError(p0: Error) < >> private val inputListener = object : InputListener < override fun onMapTap(map: Map, point: Point) < searchSession = searchManager.submit(point, 20, SearchOptions(), searchListener) >override fun onMapLongTap(map: Map, point: Point) <> > override fun onCreate(savedInstanceState: Bundle?) < super.onCreate(savedInstanceState) setApiKey(savedInstanceState) // Проверяем: был ли уже ранее установлен API-ключ в приложении. Если нет - устанавливаем его. MapKitFactory.initialize(this) // Инициализация библиотеки для загрузки необходимых нативных библиотек. binding = ActivityMainBinding.inflate(layoutInflater) // Раздуваем макет только после того, как установили API-ключ setContentView(binding.root) // Размещаем пользовательский интерфейс в экране активности moveToStartLocation() // Перемещаем камеру в определенную область на карте setMarkerInStartLocation() // Устанавливаем маркер на карте binding.mapview.map.addCameraListener(this) // Добавляем карте слушатель камеры для слежки за изменением величины зума binding.mapview.map.addTapListener(geoObjectTapListener) // Добавляем слушатель тапов по объектам searchManager = SearchFactory.getInstance().createSearchManager(SearchManagerType.ONLINE) binding.mapview.map.addInputListener(inputListener) // Добавляем слушатель тапов по карте с извлечением информации >override fun onCameraPositionChanged( map: Map, cameraPosition: CameraPosition, cameraUpdateReason: CameraUpdateReason, finished: Boolean ) < if (finished) < // Если камера закончила движение when < cameraPosition.zoom >= ZOOM_BOUNDARY && zoomValue  < placemarkMapObject.setIcon(ImageProvider.fromBitmap(createBitmapFromVector(R.drawable.ic_pin_blue_svg))) >cameraPosition.zoom = ZOOM_BOUNDARY -> < placemarkMapObject.setIcon(ImageProvider.fromBitmap(createBitmapFromVector(R.drawable.ic_pin_red_svg))) >> zoomValue = cameraPosition.zoom // После изменения позиции камеры сохраняем величину зума > > private fun setMarkerInStartLocation() < val marker = createBitmapFromVector(R.drawable.ic_pin_black_svg) mapObjectCollection = binding.mapview.map.mapObjects // Инициализируем коллекцию различных объектов на карте placemarkMapObject = mapObjectCollection.addPlacemark(startLocation, ImageProvider.fromBitmap(marker)) // Добавляем метку со значком placemarkMapObject.opacity = 0.5f // Устанавливаем прозрачность метке placemarkMapObject.setText("Обязательно к посещению!") // Устанавливаем текст сверху метки placemarkMapObject.addTapListener(mapObjectTapListener) >private fun createBitmapFromVector(art: Int): Bitmap? < val drawable = ContextCompat.getDrawable(this, art) ?: return null val bitmap = Bitmap.createBitmap( drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 ) ?: return null val canvas = Canvas(bitmap) drawable.setBounds(0, 0, canvas.width, canvas.height) drawable.draw(canvas) return bitmap >private fun moveToStartLocation() < binding.mapview.map.move( CameraPosition(startLocation, zoomValue, 0.0f, 0.0f), // Позиция камеры Animation(Type.SMOOTH, 2f), // Красивая анимация при переходе на стартовую точку null ) >private fun setApiKey(savedInstanceState: Bundle?) < val haveApiKey = savedInstanceState?.getBoolean("haveApiKey") ?: false // При первом запуске приложения всегда false if (!haveApiKey) < MapKitFactory.setApiKey(MAPKIT_API_KEY) // API-ключ должен быть задан единожды перед инициализацией MapKitFactory >> // Если Activity уничтожается (например, при нехватке памяти или при повороте экрана) - сохраняем информацию, что API-ключ уже был получен ранее override fun onSaveInstanceState(outState: Bundle) < super.onSaveInstanceState(outState) outState.putBoolean("haveApiKey", true) >// Отображаем карты перед тем моментом, когда активити с картой станет видимой пользователю: override fun onStart() < super.onStart() MapKitFactory.getInstance().onStart() binding.mapview.onStart() >// Останавливаем обработку карты, когда активити с картой становится невидимым для пользователя: override fun onStop() < binding.mapview.onStop() MapKitFactory.getInstance().onStop() super.onStop() >companion object < const val MAPKIT_API_KEY = "Ваш API-ключ" const val ZOOM_BOUNDARY = 16.4f >>

activity_main.xml

Также код можно посмотреть в GitHub.

«Яндекс. Карты» теперь весят в 10 раз меньше

Favorite

В закладки

«Яндекс. Карты» теперь весят в 10 раз меньше

Владельцы 16-гигабайтных iPhone будут довольны.

Картографическое мобильное приложение «Яндекс.Карты» получило важное обновление.

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

Согласно официальному пресс-релизу, офлайн-карта Москвы теперь занимает всего 144 МБ вместо 1,9 ГБ, офлайн-карта Санкт-Петербурга и области — 231 МБ вместо 3,2 ГБ. В реальности программа предлагала обновить карту Санкт-Петербурга, объемом 616 Мб. Лишь после полной переустановки приложения, был предложен уменьшенный вариант.

nevsky_maps

new_ya_maps

old_version_yamaps

places_ya_maps

  • Кроме того, без подключения к Интернету можно искать кафе, рестораны, магазины, банкоматы, аптеки, АЗС и другие важные объекты на карте. Достаточно лишь заранее сохранить на устройство карту нужного города или региона.
  • В управлении появилась возможность менять угол наклона карты, что поможет сориентироваться в незнакомом месте (достаточно провести двумя пальцами по экрану).

Скачать новые Яндекс.Карты, получившие обновленный дизайн, можно бесплатно в App Store.

Важно! При обновлении приложения карты, сохранённые в память ранее, будут удалены, потребуется их повторное скачивание.

(Проголосуйте первым за статью!)
�� Хочешь ещё? Читай больше в Telegram
�� Ищешь ответ на вопрос? Приходи на Форум

Владельцы 16-гигабайтных iPhone будут довольны. Картографическое мобильное приложение «Яндекс.Карты» получило важное обновление. Карты всех регионов заметно уменьшились в размере за счет перехода с растровых изображений на векторные, соответственно, больше нет надобности в нескольких вариантах одной и той же карты в разных масштабах. Согласно официальному пресс-релизу, офлайн-карта Москвы теперь занимает всего 144 МБ вместо 1,9 ГБ, офлайн-карта Санкт-Петербурга.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *