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:
-
MapWindow.screenToWorld: Converts a Screen point to a World point.
-
MapWindow.worldToScreen: Converts a World point to a Screen point.
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:
-
Target can be controlled with the scroll gesture when Map.setScrollGesturesEnabled is set to
true
. -
Zoom can be controlled with the pinch gesture or a double tap when Map.setZoomGesturesEnabled is set to
true
. -
Azimuth can be controlled by rotating two fingers when Map.setRotateGesturesEnabled is set to
true
. -
Tilt can be controlled by swiping two fingers vertically when Map.setTiltGesturesEnabled is set to
true
.
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:
-
Name
-
Description
-
Geometry
-
Attributes
-
Collection of metadata, such as GeoObjectSelectionMetadata and UriObjectMetadata