Skip to content

Handle gestures and clicks

The map supports pan, zoom, rotate, and tilt gestures. GestureOptions presets cover the common cases:

App.kt
MaplibreMap(options = MapOptions(gestureOptions = GestureOptions.Standard))

To enable or disable gestures individually, construct GestureOptions with individual fields:

App.kt
MaplibreMap(
options =
MapOptions(
gestureOptions =
GestureOptions(
isTwoFingerTiltEnabled = true,
isPinchZoomEnabled = true,
isTwoFingerRotateEnabled = true,
isDragPanEnabled = true,
)
)
)

onMapClick and onMapLongClick receive the clicked position and its screen offset. To identify the clicked feature, query rendered features with CameraState.queryRenderedFeatures. The query suspends, so launch it in a coroutine. Return ClickResult.Pass to send the click on to the layer listeners:

App.kt
val scope = rememberCoroutineScope()
MaplibreMap(
cameraState = camera,
onMapClick = { pos, offset ->
scope.launch {
val features = camera.queryRenderedFeatures(offset)
if (features.isNotEmpty()) {
println("Clicked on ${features[0].toJson()}")
}
}
ClickResult.Pass
},
onMapLongClick = { pos, offset ->
println("Long click at $pos")
ClickResult.Pass
},
)

Layer composables have click listeners of their own, which receive the features that were clicked in that layer:

App.kt
MaplibreMap {
CircleLayer(
id = "amtrak-stations",
source = amtrakStations,
onClick = { features ->
println("Clicked on ${features[0].toJson()}")
ClickResult.Consume
},
)
}

Click listeners run on the map first, then on layers from the top to the bottom of the map. The first listener that returns ClickResult.Consume stops the event from reaching later listeners.