Integrating MapsIndoors SDKs with Modern UI Frameworks
Introduction
As mobile app development evolves, declarative UI frameworks like SwiftUI for iOS and Jetpack Compose for Android have gained significant traction. These frameworks offer a more intuitive approach to building user interfaces with less code and greater flexibility. This guide explains how to integrate the MapsIndoors SDKs (which are built using traditional UIKit and Android Views) with these modern frameworks.
Understanding Modern UI Frameworks
The Declarative UI Paradigm
Modern UI frameworks like SwiftUI and Jetpack Compose use a declarative approach to building interfaces, which differs from the imperative approach used in traditional frameworks:
Traditional UI frameworks (UIKit, Android Views) require detailed, step-by-step instructions for creating and updating UI elements
Declarative frameworks allow developers to define what the UI should look like for a given state, and the framework handles the updates automatically
This approach simplifies development by reducing boilerplate code and making UI behavior more predictable.
Automatic Layout Adaptation
One significant advantage of SwiftUI and Jetpack Compose is their built-in layout engines that automatically adapt to different screen sizes and orientations. Rather than manually positioning elements for every possible configuration, these frameworks intelligently adjust layouts based on available space and device characteristics.
Integration Approach
The MapsIndoors SDKs can be seamlessly integrated with SwiftUI and Jetpack Compose through a simple wrapping process. This allows you to:
Continue using the rich functionality of the MapsIndoors SDK
Take advantage of the modern UI frameworks for the rest of your application
Maintain a consistent development experience
Wrapping MapsIndoors Components
Since the core MapsIndoors SDK uses traditional UI components (UIKit for iOS and Android Views for Android), integration requires creating wrapper components that bridge these elements to the modern frameworks.
For SwiftUI
The Apple documentation explains how to wrap a UIKit view (which the MapsIndoors map view is for both Mapbox Maps and Google Maps) in their documentation, and they provide a tutorial with an example of how to use UIViewControllerRepresentable
.
The approach is identical for using MapsIndoors with SwiftUI, where the Mapbox MapView
or the Google Maps GMSMapView
takes the place of the UIView
that is wrapped. A simple example using Mapbox Maps to get you started is provided here.
class MapboxViewController: UIViewController {
var solution: String!
private var mapView: MapView!
private var mapControl: MPMapControl?
override public func viewDidLoad() {
super.viewDidLoad()
initializeMap()
loadMapsIndoors()
}
private func initializeMap() {
let cameraOptions = CameraOptions(
center: CLLocationCoordinate2D(latitude: 40.75596, longitude: -73.97608),
zoom: 23,
bearing: 70,
pitch: 50
)
let options = MapInitOptions(cameraOptions: cameraOptions)
mapView = MapView(frame: view.bounds, mapInitOptions: options)
self.view.addSubview(mapView)
}
private lazy var mapConfig = {
let config = MPMapConfig(
mapBoxView: mapView,
accessToken: "<YOUR_MAPBOX_TOKEN>"
)
return config
}()
private func loadMapsIndoors() {
guard let mapboxMap = mapView.mapboxMap else { return }
mapboxMap.loadStyle(.standard) { _ in
Task {
do {
try await MPMapsIndoors.shared.load(apiKey: self.solution)
mapControl = MPMapsIndoors.createMapControl(mapConfig: mapConfig)
await self.goToInitialMapPosition()
} catch {
print(error.localizedDescription)
}
}
}
}
private func goToInitialMapPosition() async {
let loc = await MPMapsIndoors.shared.locationsWith(query: nil, filter: nil).first!
self.mapControl?.goTo(entity: loc, maxZoom: 21)
}
}
struct MapsIndoorsNativeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
let miView = MapboxViewController()
miView.solution = solution.rawValue
miView.delegate = context.coordinator
return miView
}
func updateUIViewController(_: UIViewController, context _: Context) { }
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
For Jetpack Compose
The Android documentation explains how to wrap a View (which the MapsIndoors MapControl
uses for both Mapbox Maps and Google Maps) in a composition using the AndroidView
composable.
The approach is identical for Mapbox Maps and Google Maps, using MapView
with both. A simple example to get you started is provided here using Mapbox Maps:
class MainActivity : ComponentActivity(), OnViewReady {
private var mapControl: MapControl? = null
private var mapboxMap: MapboxMap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
MapsIndoors.load(applicationContext, "YOUR_MAPSINDOORS_API_KEY") { e -> }
setContent {
ComposeExampleTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
MapboxView(
mapInitOptions = MapInitOptions(baseContext),
modifier = Modifier.padding(innerPadding),
callback = this
)
}
}
}
}
override fun onViewReady(mapView: MapView, mapboxMap: MapboxMap) {
this.mapboxMap = mapboxMap
val config = MPMapConfig.Builder(baseContext, mapboxMap, mapView, "YOUR_MAPBOX_API_KEY", true).build()
MapControl.create(config) { mc, e ->
mapControl = mc
goToDefaultVenue()
}
}
fun goToDefaultVenue() {
mapControl?.goTo(MapsIndoors.getVenues()?.defaultVenue)
}
}
@Composable
fun MapboxView(mapInitOptions: MapInitOptions, modifier: Modifier = Modifier, callback: OnViewReady? = null) {
AndroidView(
modifier = modifier,
factory = { context ->
MapView(context, mapInitOptions).also {
callback?.onViewReady(mapView = it, mapboxMap = it.mapboxMap)
}
}
)
}
interface OnViewReady {
fun onViewReady(mapView: MapView, mapboxMap: MapboxMap)
}
Key Integration Considerations
When integrating MapsIndoors with these frameworks, keep in mind:
The core functionality of the MapsIndoors SDK remains unchanged
The wrapper simply handles the UI integration aspects
You can create custom wrappers tailored to your specific needs
The process is straightforward and requires minimal code
Benefits of Integration
Improved Developer Experience
By integrating MapsIndoors with SwiftUI or Jetpack Compose, you can:
Work with a more intuitive programming model
Reduce the amount of code needed for UI implementation
Benefit from live previews during development
More easily implement animations and transitions
Enhanced User Experience
The integration also improves the end-user experience by:
Ensuring UI consistency across your entire application
Enabling smoother integration with other modern UI components
Supporting more responsive layouts across device types
Facilitating more dynamic and interactive interfaces
Last updated
Was this helpful?