Picture-in-Picture (PiP) Map Mode
Picture-in-Picture lets the map shrink to a compact, glanceable panel — showing just the map canvas, floor selector, compass, and locate-me button — while the user does something else in your app, then expand back to the full experience. It is designed for the route and navigation flow: keep a small live map visible while the rest of the screen shows your own content.
Availability
New in iOS SDK 26.7.1. The PiP API is on MapstedMapUiViewController (import MapstedMapUi). PiP is opt-in — it is completely inactive until you enable it.
Concepts: enabled vs allowed
Two independent conditions govern PiP:
- Enabled — you turn the feature on with
setPipMode(enable:). Until you do, every PiP call is a no-op and the SDK behaves exactly as if PiP did not exist. Check withisPipModeEnabled(). - Allowed — whether the SDK will accept a collapse right now. PiP collapse is only meaningful during route preview or active navigation, so
isPipModeAllowed()reflects that state. Expanding is always allowed.
The mode itself is MapstedPipMode:
| Case | Meaning |
|---|---|
.collapsed |
Compact map — only the map canvas, floor selector, compass, and locate-me are shown; all panels are suppressed. |
.expanded |
Full map — panels are reconstructed from the current SDK state (active route, selected entity, …). |
Enabling PiP and observing changes
Enable PiP, register a delegate to hear about mode changes, and switch modes with applyPipMode(_:). Mode changes are delivered on the main thread.
Android: Picture-in-Picture map mode is an iOS-only feature in 26.7.1 and is not available on Android.
import UIKit
import MapstedMapUi
final class MapHostViewController: UIViewController, MapstedPipModeDelegate {
// MapstedMapUiViewController.shared is typed UIViewController?; cast it.
private var mapVC: MapstedMapUiViewController? {
MapstedMapUiViewController.shared as? MapstedMapUiViewController
}
func enablePiP() {
guard let mapVC = mapVC else { return }
mapVC.setPipMode(enable: true) // opt in
mapVC.addPipModeDelegate(self) // observe mode changes
}
func collapse() {
guard let mapVC = mapVC, mapVC.isPipModeAllowed() else { return }
mapVC.applyPipMode(.collapsed)
}
func expand() {
mapVC?.applyPipMode(.expanded) // always allowed
}
func disablePiP() {
guard let mapVC = mapVC else { return }
mapVC.removePipModeDelegate(self)
mapVC.setPipMode(enable: false) // resets any active PiP state to .expanded
}
// MARK: - MapstedPipModeDelegate
func mapstedPipModeDidChange(to mode: MapstedPipMode) {
switch mode {
case .collapsed:
// Resize your container to the compact height.
break
case .expanded:
// Restore your container to full size.
break
@unknown default:
break
}
}
// Optional — a mode change was rejected (for example, collapse when not allowed).
func mapstedPipModeDidFail(reason: String) {
print("PiP change rejected: \(reason)")
}
}
mapstedPipModeDidChange(to:) is the one method you must implement; mapstedPipModeDidFail(reason:) is optional (it has a default empty implementation) — implement it if you want to tell the user why a collapse was refused.
Typical flow
- Call
setPipMode(enable: true)once, when your map screen appears. - Register your delegate with
addPipModeDelegate(_:). - Start a route or navigation, then call
applyPipMode(.collapsed)— guard it withisPipModeAllowed(). - In
mapstedPipModeDidChange(to:), resize the container that hosts the map. - Call
applyPipMode(.expanded)to return to the full map (always succeeds). - When you leave the screen,
removePipModeDelegate(_:)andsetPipMode(enable: false).
Tips & Considerations
- PiP is opt-in. Nothing happens until
setPipMode(enable: true).isPipModeEnabled()returnsfalseby default. - Collapse can be refused. If
isPipModeAllowed()isfalse,applyPipMode(.collapsed)does not collapse and your delegate'smapstedPipModeDidFail(reason:)is called. Expanding always works. - Disabling resets state.
setPipMode(enable: false)restores panels, zoom, and sets the mode back to.expanded. - Delegate callbacks are on the main thread — you can update UI directly.
MapstedMapUiViewController.sharedis typedUIViewController?— cast withas? MapstedMapUiViewController(shown above).