Перейти к содержанию

Объекты базовой карты

Всё, что рисует сам MapKit — POI, здания, топонимы, дороги, — это объекты базовой карты. Вы их не создаёте; вы реагируете на нажатия по ним и читаете их метаданные.

Реакция на нажатие

GeoObjectTapListener срабатывает раньше, чем InputListener карты. Вернуть true — поглотить событие, false — пропустить его дальше, в onMapTap.

class GeoObjectController(private val map: Map) {

    private val tapListener = GeoObjectTapListener { event ->
        val geoObject = event.geoObject
        println("${geoObject.name}: ${geoObject.descriptionText}")
        false
    }

    init {
        map.addTapListener(tapListener.asWeakRef())
    }
}

event.isValid говорит, пригодно ли событие: оно инвалидируется, как только колбэк вернул управление, поэтому ничего из него нельзя сохранять на потом.

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

MapKit умеет подсветить нажатый объект своим стилем выделения — так делает приложение Яндекс.Карт при нажатии на POI. Для этого нужны GeoObjectSelectionMetadata объекта:

private val tapListener = GeoObjectTapListener { event ->
    val metadata = event.geoObject.selectionMetadata ?: return@GeoObjectTapListener false
    map.selectGeoObject(metadata)
    true
}

map.deselectGeoObject() снимает выделение.

Вернуть здесь true важно: если событие пойдёт дальше, нажатие дойдёт ещё и до onMapTap со всем, что там происходит.

Чтение метаданных

MapKit держит метаданные объекта в словаре с ключами-нативными классами, у которого нет общего представления. Обёртка отдаёт те записи, которые прикрепляет lite SDK, каждую как nullable-свойство:

Свойство Тип Что несёт
selectionMetadata GeoObjectSelectionMetadata objectId, dataSourceName, layerId, groupId — то, что нужно selectGeoObject
inspectionMetadata GeoObjectInspectionMetadata layerId и ObjectTypePOINT, POLYLINE, POLYGON, CIRCLE
tags GeoObjectTags список тегов объекта, например вид POI
uriMetadata UriObjectMetadata Uri, которые идентифицируют объект в других сервисах Яндекса
personalizedPoiMetadata PersonalizedPoiExtraMetadata пары ключ/значение персонализированного POI
private val tapListener = GeoObjectTapListener { event ->
    val geoObject = event.geoObject

    val kind = geoObject.tags?.tags?.firstOrNull()
    val uri = geoObject.uriMetadata?.uris?.firstOrNull()?.value
    val type = geoObject.inspectionMetadata?.objectType

    println("$kind $type $uri")
    false
}

Сам объект

Свойство Тип
name String?
descriptionText String?
geometry List<Geometry>
boundingBox BoundingBox?
aref List<String>
attributionMap Map<String, Attribution>

geometry — список, потому что один объект может состоять из нескольких фигур. В каждой Geometry заполнено ровно одно из point, polyline, polygon, multiPolygon, boundingBox, circle.

val point = geoObject.geometry.firstNotNullOfOrNull { it.point }

if (point != null) {
    map.move(
        CameraPosition(point, zoom = 17f, azimuth = 0f, tilt = 0f),
        Animation(Animation.Type.SMOOTH, 300.milliseconds),
    )
}

attributionMap сопоставляет идентификатор атрибуции с Attribution, где лежат author, link и avatarImage — то, что нужно показать рядом со сторонними данными.

Приблизиться к нажатому объекту

private val tapListener = GeoObjectTapListener { event ->
    val box = event.geoObject.boundingBox ?: return@GeoObjectTapListener false
    map.move(
        map.cameraPosition(box.toGeometry()),
        Animation(Animation.Type.SMOOTH, 300.milliseconds),
    )
    true
}

В Compose

MapListeners подключает тот же слушатель на время нахождения в композиции:

YandexMap(modifier = Modifier.fillMaxSize()) {
    MapListeners(
        onGeoObjectTap = { event ->
            val metadata = event.geoObject.selectionMetadata ?: return@MapListeners false
            selection = metadata
            true
        },
    )
    MapEffect(selection) { map ->
        val metadata = selection
        if (metadata != null) map.selectGeoObject(metadata) else map.deselectGeoObject()
    }
}

Идентификаторы слоёв

layerId в метаданных — один из идентификаторов, которыми MapKit называет свои слои; они перечислены в LayerIds:

LayerIds.mapLayerId
LayerIds.jamsLayerId
LayerIds.buildingsLayerId
LayerIds.transportLayerId
LayerIds.mapObjectsLayerId
LayerIds.userLocationLayerId

С ними же вы сравниваете идентификатор, когда добавляете собственный слой — см. Слои и тайлы.