WemapMap

fun WemapMap(session: MapSession, modifier: Modifier = Modifier, config: MapViewConfig = MapViewConfig(), initialCamera: MapCameraState? = null, cameraPositionState: MapCameraPositionState? = null, cameraUpdateFrequency: MapUpdateFrequency = MapUpdateFrequency.ON_END, proxyUpdateFrequency: MapUpdateFrequency = MapUpdateFrequency.ON_END, onLoaded: (WemapMapView) -> Unit? = null, onFailed: (Throwable) -> Unit? = null, onPhaseChange: (LoadPhase) -> Unit? = null, onTouch: (PointF) -> Unit? = null, onProxyUpdate: (MapProxy) -> Unit? = null, factory: (Context) -> WemapMapView? = null)

Displays a Wemap map.

The map view itself is handed to onLoaded once it has finished loading, and everything the SDK offers is reached through it — managers, camera, navigation. Hold it in a remember if you need it outside the callback; it is a handle, not composable state.

var mapView by remember { mutableStateOf<WemapMapView?>(null) }

WemapMap(
session = session,
modifier = Modifier.fillMaxSize(),
onLoaded = { mapView = it },
onFailed = { error -> Log.e("Map", "Failed to load", error) }
)

// the SDK's own flows are collected directly — no wrapper parameters needed
val focusedBuilding by (mapView?.buildingManager?.focusedBuildings ?: emptyFlow())
.collectAsStateWithLifecycle(null)

The map is tied to session: because a view's session is set once and cannot be replaced, passing a different session tears the map down and builds a new one. Sharing one session across a WemapMap, a GeoARView and the screen's location sources is what keeps navigation, POI selection and user location consistent, and the session must outlive the composable — hoist it into a ViewModel rather than a remember, or a configuration change will drop it.

Parameters

session

the session this map renders. Create it once per screen and share it.

modifier

the Modifier applied to the map.

config

rendering configuration. Read once, when the map is created — later changes are ignored, exactly as with WemapMapView.configure.

initialCamera

the camera the map opens at, instead of the one derived from the map data. Read once, when the map is created. Use WemapMapView.map from onLoaded to move the camera afterwards. Ignored when cameraPositionState already carries a position — a two-way state is the live source of truth and wins.

cameraPositionState

two-way camera state. The map writes every settled camera into it, and assigning its position moves the map — without animating (see MapCameraPositionState). Omit it when the camera is not app state: reading the camera does not need it (onProxyUpdate, or the view's own cameraStates).

cameraUpdateFrequency

how often cameraPositionState is written back to. MapUpdateFrequency.CONTINUOUS recomposes every reader on every frame of every gesture, so prefer the default.

proxyUpdateFrequency

how often onProxyUpdate is invoked. MapUpdateFrequency.CONTINUOUS fires once per frame of every gesture, so prefer the default unless you genuinely need per-frame reads.

onLoaded

invoked once with the loaded map view. Its managers are available from this point on.

onFailed

invoked with the error when loading fails. A failure to load the map itself leaves the managers unbuilt, while a failed points-of-interest download leaves them all usable — see LoadPhase.Failed.

onPhaseChange

invoked on every load-phase transition, including the initial LoadPhase.Loading. Use it to drive a spinner; onLoaded and onFailed cover the terminal states.

onTouch

invoked with the tapped point, in the map's coordinate system, for taps that selected no Point of Interest. Collect pointOfInterestManager.touchedPois for the ones that did.

onProxyUpdate

invoked with a read-only view onto the camera and geometry whenever the camera changes.

factory

builds the map view, for integrators with a WemapMapView subclass. Do not call configure in it — this composable does that. Read once, when the map is created.