Map interaction

Maps are a key entity in the MapKit SDK. Users can navigate maps with special gestures.

This section describes the MapKit SDK's main features for implementing map interactions.

Coordinates

MapKit SDK uses two coordinate systems:

  • World: The real-world position of a point represented by the Point class. Points are defined by geographic coordinates, with latitude ranging from -90 to 90 and longitude ranging from -180 to 180.

  • Screen: The screen coordinate system represented by the ScreenPoint class. Sets a point relative to the screen size of the device in pixels. The coordinates range from the upper-left (0, 0) to the lower-right corner of the screen (MapWindow.width, MapWindow.height).

Here's how you can convert coordinates from one system to another:

Adding a map placemark positioned in the center of the screen:

val centerX = mapWindow.width / 2f
val centerY = mapWindow.height / 2f
val centerPoint = ScreenPoint(centerX, centerY)
// For example, worldPoint = (25.1982, 55.272758)
val worldPoint = mapWindow.screenToWorld(centerPoint)
map.mapObjects.addPlacemark().apply {
    geometry = worldPoint
    setIcon(ImageProvider.fromResource(this, R.drawable.ic_pin))
}

The code snippet above displays a placemark in the center of the map UI component.

Camera

You can move, rotate, tilt, and zoom the MapKit SDK camera with screen gestures or programmatically. That is handled by the camera, a separate entity that controls how the map is displayed on the user's device.

Camera position

The camera position is represented by the CameraPosition class. To get the current camera position, use Map.getCameraPosition.

Here are the parameters that define the camera position.

Target

Map position. Displays the location that corresponds to the coordinates of the screen focus point.

Zoom

Map zoom level. The higher the zoom value, the more detailed the map's base level becomes. At the CameraBounds.getMaxZoom zoom level, the map is displayed at maximum zoom, while you can see the entire world map at the CameraBounds.getMinZoom zoom level.

Azimuth

Camera direction. The camera angle relative to north as measured in degrees, which is responsible for camera rotation. As you increase the azimuth value, the map rotates counterclockwise. The azimuth ranges from 0 to 360 degrees.

Tilt

Camera tilt value. Determines the angle between the camera and the map's surface. A tilt value of 0 results in a top-down perspective, while higher values increase the angle at which the map is displayed.

Camera movement

To move the camera, call the Map.move method, which applies a new position value to it.

val cameraCallback = object : CameraCallback {
    override fun onMoveFinished(isFinished: Boolean) {
        // Handle camera move finished ...
    }
}

map.move(
    CameraPosition(
        /* target */ Point(25.1982, 55.272758)
        /* zoom */ 13f,
        /* azimuth */ 0f,
        /* tilt */ 0f,
    ),
    Animation(Animation.Type.LINEAR, 1f),
    cameraCallback
)

Use the Animation object to set the camera movement animation as well as its type and duration. The last parameter, CameraCallback, is optional. You can use it to subscribe to camera movement completion events.

Focusing the camera on an object

One common camera movement scenario is focusing on an object.

Focusing the camera on a separate placemark is easy. To do so, use the camera movement method and pass the placemark position as an argument.

If the object you want to focus on is an area of the map, use the Map.cameraPosition method. It takes the object geometry as the input and returns a CameraPosition value. Once the camera finishes moving to that position, it automatically focuses on the object, working around the map viewport boundaries.

With Map.cameraPosition, you can get a new camera position (for example, to focus on a polyline object) and move the camera to it.

val geometry = Geometry.fromPolyline(polyline)
val position = Map.cameraPosition(
    geometry,
    /* azimuth */ null,
    /* tilt */ null,
    /* focusRect */ null
)
map.move(position)

In addition to object geometry, Map.cameraPosition also takes camera position values to be applied during movement.

Focus rect

Many map apps have an additional custom UI displayed on top of the MapKit SDK map. In those cases, calculating the correct camera position such that it accounts for the covered areas of the map can be a challenge. MapKit SDK provides a tool that solves that problem.

Focus rect sets the map area used when calculating the camera position. To change its value, use MapWindow.setFocusRect. The entire map area is used by default.

Using the focus rect logic to focus on an object's geometry:

In the first screenshot, the polyline object is partially covered by user UI elements: the map at the bottom and the zoom controls on the right. In the second example, the focus rect area was calculated based on the size of the UI elements.

Focus rect calculation code:

val bottomPadding = binding.layoutBottomCard.measuredHeight
val rightPadding = binding.buttonMinus.measuredWidth

mapWindow.focusRect = ScreenRect(
    ScreenPoint(0f, 0f),
    ScreenPoint(
        mapWindow.width().toFloat() - rightPadding,
        mapWindow.height().toFloat() - bottomPadding,
    )
)

Focus point

Focus point is the screen point that serves as a reference for camera movement and calculating the camera position. For example, when you call the Map.move method, the camera moves to the screen focus point. Use MapWindow.setFocusPoint to change its value. If the point isn't set, the center of the current focus rect is used instead by default.

Map events

The MapKit SDK supports a wide range of map events, including tapping, a variety of gestures, and camera position changes.

Tapping

You can use the InputListener interface to subscribe to map tap events.

val inputListener = object : InputListener {
    override fun onMapTap(map: Map, point: Point) {
        // Handle single tap ...
    }

    override fun onMapLongTap(map: Map, point: Point) {
        // Handle long tap ...
    }
}
map.addInputListener(inputListener)

There are two types of map tap events: regular and long. Both types provide information on the map and the coordinates where the user tapped.

Gestures

The map can recognize user gestures. Each camera position parameter can be changed with an associated gesture:

Map loading

You can subscribe to successful map load events using the MapLoadedListener interface. Maps are considered loaded when all their current tiles are downloaded. In some cases, the map can take a while to load, perhaps if the user is continuously scrolling or doesn't have an internet connection.

Note

The map load event notification is only triggered once, when all visible tiles are loaded and displayed. To get new event notifications, resubscribe to the MapLoadedListener interface.

Changing the camera position

To track the camera in real time, subscribe to camera position change events in the CameraListener interface.

Map resizing

Use the SizeChangedListener interface to subscribe to map resize events.

val sizeChangedListener = object : SizeChangedListener {
    override fun onMapWindowSizeChanged(mapWindow: MapWindow, width: Int, height: Int) {
        // Handle window size changed ...
    }
}

POI

POIs (points of interest) are special MapKit map points that indicate interesting locations, objects, or organizations. They can include stores, restaurants, museums, sights, parks, or any other locations that may be of interest to the user.

The MapKit SDK supports interaction with POIs.

POI taps

Use the GeoObjectTapListener interface to handle POI tap events.

val geoObjectTapListener = object : GeoObjectTapListener {
    override fun onObjectTap(event: GeoObjectTapEvent): Boolean {
        // Handle GeoObjectTapEvent ...
    }
}
map.addTapListener(geoObjectTapListener)

The tap event handler method takes a GeoObjectTapEvent object, which encapsulates information about the map object that was tapped.

POI selection

To select a POI on the map, use the Map.selectGeoObject method. You can then deselect it using the Map.deselectGeoObject method.

Geo objects

You can access information about a geo-object by calling GeoObjectTapEvent.getGeoObject.

The GeoObject class is a MapKit SDK entity that provides information about map objects. A geo object can be an organization, a building, or a geographic object like a country, city, or sea.

GeoObject contains a large number of methods, providing access to the following data: