Skip to main content

Indoor mapping

The Mapbox Maps SDK for Android provides indoor mapping support, allowing your application to display detailed floor plans inside buildings and let users switch between floors. Indoor mapping is part of the Mapbox Standard style and is controlled via a style configuration property.

Experimental API

Indoor mapping is an experimental feature. APIs may change in future releases. You must opt in with the @OptIn(MapboxExperimental::class) annotation.

Enable indoor mapping

Indoor mapping is included in the Mapbox Standard style, but the feature is disabled by default. To enable it, set the showIndoor configuration property on the basemap style import to true.

mapView.mapboxMap.loadStyle(Style.STANDARD) { style ->
mapView.mapboxMap.setStyleImportConfigProperty("basemap", "showIndoor", Value.valueOf(true))
}

Once enabled, buildings that have indoor map data will render their indoor floor plans at appropriate zoom levels.

Indoor selector plugin

The indoor selector plugin provides a floor selection UI that lets users browse and switch between floors in an indoor-mapped building.

Setup

To use the indoor selector plugin, you need to include it in the MapInitOptions plugin list and then enable it:

@OptIn(MapboxExperimental::class)
val mapInitOptions = MapInitOptions(
context = this,
cameraOptions = cameraOptions {
center(Point.fromLngLat(LONGITUDE, LATITUDE))
zoom(16.0)
bearing(12.0)
pitch(60.0)
},
styleUri = Style.STANDARD,
// Add the indoor selector plugin to the default plugin list
plugins = MapInitOptions.defaultPluginList + Plugin.Mapbox(Plugin.MAPBOX_INDOOR_SELECTOR_PLUGIN_ID)
)

val mapView = MapView(this, mapInitOptions)

After the MapView is created, enable the indoor selector and configure its position:

// Enable the floor selector UI
mapView.indoorSelector.enabled = true

// Optionally adjust the top margin to avoid overlapping with other controls
mapView.indoorSelector.marginTop = 160f

Floor selection

When the indoor selector plugin is enabled, it automatically subscribes to IndoorManager updates. As the user pans the map to a building with indoor data, the selector populates with available floors and allows the user to tap on a floor to switch the view.

You can also listen for floor selection events by adding a listener:

@OptIn(MapboxExperimental::class)
mapView.indoorSelector.addOnFloorSelectedListener { floorId ->
Log.d(TAG, "Floor selected: $floorId")
}

Indoor manager

The IndoorManager is the core API for programmatic control of indoor mapping. It provides access to the current indoor state including available floors and the selected floor.

Experimental API

The IndoorManager programmatic API is experimental and subject to change. In future releases, this API may be extended to allow full customization of the indoor control, including building custom floor selector UI.

Observing indoor state

You can subscribe to indoor state updates to be notified when the available floors change (e.g., when panning to a new building) or when a floor is selected:

@OptIn(MapboxExperimental::class)
val cancelable = mapView.mapboxMap.subscribeOnIndoorUpdated { indoorState ->
val floors = indoorState.floors
val selectedFloor = indoorState.selectedFloorId
Log.d(TAG, "Floors: ${floors.map { it.id }}, selected: $selectedFloor")
}

// Later, cancel the subscription when no longer needed
cancelable.cancel()

Programmatic floor selection

To select a floor programmatically, use the IndoorManager.selectFloor() method:

@OptIn(MapboxExperimental::class)
mapView.mapboxMap.indoorManager.selectFloor("floor-2")

// Pass null to deselect and show the building overview
mapView.mapboxMap.indoorManager.selectFloor(null)

Disable indoor mapping

To completely disable indoor mapping after it was enabled, you should both turn off the style configuration and disable the indoor selector plugin.

Disable style configuration

Set the showIndoor configuration property to false:

mapView.mapboxMap.setStyleImportConfigProperty("basemap", "showIndoor", Value.valueOf(false))

Disable indoor selector plugin

Set the enabled property of the indoor selector to false:

mapView.indoorSelector.enabled = false

Complete example

Here's a complete example showing how to set up indoor mapping with the floor selector:

@OptIn(MapboxExperimental::class)
class IndoorActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val mapInitOptions = MapInitOptions(
context = this,
cameraOptions = cameraOptions {
center(Point.fromLngLat(139.794131, 35.55025))
zoom(16.0)
bearing(12.0)
pitch(60.0)
},
styleUri = Style.STANDARD,
plugins = MapInitOptions.defaultPluginList +
Plugin.Mapbox(Plugin.MAPBOX_INDOOR_SELECTOR_PLUGIN_ID)
)

setContentView(R.layout.activity_indoor)
val mapView = MapView(this, mapInitOptions)
findViewById<ViewGroup>(R.id.container).addView(mapView, 0)

// Enable indoor in the Standard style
mapView.mapboxMap.loadStyle(Style.STANDARD) { style ->
mapView.mapboxMap.setStyleImportConfigProperty(
"basemap", "showIndoor", Value.valueOf(true)
)
}

// Enable the floor selector UI
mapView.indoorSelector.enabled = true
mapView.indoorSelector.marginTop = 160f

// Enable scale bar
mapView.scalebar.enabled = true
}
}
Was this page helpful?