Handle map input and clicks
Users can pan, zoom, rotate, and tilt the map by default. Pass MapInteractions to
customize controls or respond to input. The configuration has three parts:
camera: which movements the controls allow, such as panning or rotation.bindings: what gestures, scrolling, and keys do.callbacks: how your app responds to clicks.
Restrict camera movement
Section titled “Restrict camera movement”For a map that users can pan and zoom but cannot rotate or tilt, disable those camera movements:
MaplibreMap( interactions = MapInteractions { camera { rotate { enabled = false } tilt { enabled = false } } })Omitted settings keep their defaults. Use MapInteractions(from = existing)
to build on another configuration, or MapInteractions.None to disable
built-in input, including feature clicks.
To stop following the user’s location when they
pan, use camera.pan.onStart.
This hook runs before the component responds to input and can run again within
the same gesture. It does not report when camera movement ends.
For moving the camera from app code, see Control the camera.
Change scroll controls
Section titled “Change scroll controls”Vertical scrolling zooms by default. This example makes scrolling pan the map, while Ctrl-scroll zooms:
MaplibreMap( interactions = MapInteractions { bindings { scroll { mappings { on(modifiers = Containing(KeyModifier.Ctrl), response = ScrollResponse.Zoom) otherwise(ScrollResponse.Pan) } } } })A mappings block replaces the default responses for that input. Rows are
tried from top to bottom; otherwise handles the remaining input. Available
gestures depend on the input device and Compose host.
A null pointer-type, button, or modifier filter matches any value. Key mappings
default to exactly no modifiers; set modifiers = null to match a key with any
modifiers.
Handle map clicks
Section titled “Handle map clicks”Use callbacks.click to act on a geographic location. For example, pass the
clicked position to your app:
@Composablefun ClickableMap(onLocationSelected: (Position) -> Unit) { MaplibreMap( interactions = MapInteractions { callbacks { click { onEvent { event -> event.position?.let(onLocationSelected) ClickResult.Consume } } } } )}Return ClickResult.Consume when your app handles the click, or
ClickResult.Pass to let it continue to interactive layers.
Use longClick for a long press or secondary mouse click.
Select layer features
Section titled “Select layer features”A layer’s onClick receives the features under the pointer. Use hitPadding
to make small features easier to select:
val state = rememberMapState { val interactiveAmtrakStations = rememberGeoJsonSource(GeoJsonData.Uri(Res.getUri("files/data/amtrak_stations.geojson"))) CircleLayer( id = "amtrak-stations", source = interactiveAmtrakStations, hitPadding = 12.dp, onClick = { features -> println("Clicked on ${features[0].toJson()}") ClickResult.Consume }, )}MaplibreMap(state = state)Layers receive clicks from front to back until a handler returns
ClickResult.Consume. Use callbacks.click.onUnhandled for clicks that no
layer handles, such as clearing an app’s selection.
Snap rotation to bearings
Section titled “Snap rotation to bearings”Use camera.rotate.snapping to snap to nearby bearings after rotation ends.
Choose specific bearings or evenly spaced targets, such as the four cardinal
directions:
MaplibreMap( interactions = MapInteractions { camera { rotate { snapping { targets = BearingTargets.evenlySpaced(count = 4) tolerance = 7.0 } } } })Feel bearing notches
Section titled “Feel bearing notches”Use camera.rotate.haptics to add feedback at chosen bearings while rotating.
Haptics work independently of snapping and support Android, iOS, and macOS.
Combine notches with different emphasis levels:
MaplibreMap( interactions = MapInteractions { camera { rotate { haptics { notch(BearingTargets.evenlySpaced(24), HapticEmphasis.Subtle) notch(BearingTargets.evenlySpaced(4), HapticEmphasis.Standard) notch(BearingTargets.at(0.0), HapticEmphasis.Emphasized) } } } })