Skip to content
This site is a preview of pull request #1384.

Present outside Compose UI

MaplibreMap provides the map’s Compose UI integration. When another framework owns the UI, such as Android Auto, CarPlay, UIKit, or SwiftUI, use a platform presentation to reuse the same map state, camera operations, and declarative styles.

Create a MapState with MapRuntime.createMapState and pass it to a presentation. Your application supplies the host, manages its lifecycle, and forwards recognized gestures through the map’s input methods. Compose UI dependencies are still required, but a Compose UI hierarchy is not.

AndroidMapPresentation draws into an Android Surface, such as one supplied by Android Auto. Connect the presentation to the host’s lifecycle and surface callbacks:

SurfaceMapHost.kt
/** Your code owns the MapState and each Surface. Call these methods on the main thread. */
class SurfaceMapHost(context: Context, state: MapState, lifecycle: Lifecycle) : AutoCloseable {
val presentation = AndroidMapPresentation(context, state, lifecycle)
private var binding: AndroidMapPresentation.SurfaceBinding? = null
fun onSurfaceAvailable(surface: Surface, width: Int, height: Int, density: Float) {
binding = presentation.attachSurface(surface, width, height, density)
}
fun onSurfaceChanged(width: Int, height: Int, density: Float) {
binding?.update(width, height, density)
}
fun onSurfaceDestroyed() {
binding?.close()
binding = null
}
fun onConfigurationChanged(configuration: Configuration) {
presentation.updateConfiguration(configuration)
}
override fun close() {
presentation.close()
}
}

The Android Auto demo shows a complete car-app integration. See AndroidMapPresentation for configuration, surface ownership, and lifecycle contracts.

AppleMapPresentation presents the map, and MaplibreMapView supplies a UIKit view that manages the Metal layer and its layout:

UIKitMapHost.kt
/** The caller owns the MapState. Create and use this host on the main thread. */
class UIKitMapHost(state: MapState) : AutoCloseable {
val presentation = AppleMapPresentation(state, isActive = false)
val view: UIView = MaplibreMapView(presentation)
fun onSceneActivationChanged(active: Boolean) {
presentation.isActive = active
}
override fun close() {
view.removeFromSuperview()
presentation.close()
}
}

Add the view to a UIKit or CarPlay view hierarchy, or return it from SwiftUI’s UIViewRepresentable.makeUIView. Forward activation from the scene hosting the map; CarPlay has a separate scene from the phone’s UI. The CarPlay demo shows the scene integration. See MaplibreMapView and AppleMapPresentation for ownership, configuration, and lifecycle contracts.

For hosts that already manage a Metal layer, use AppleMapPresentation.attachLayer directly. This is the same attachment API used by MaplibreMapView.