# 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:

1. Continue using the rich functionality of the MapsIndoors SDK
2. Take advantage of the modern UI frameworks for the rest of your application
3. 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](https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable) 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](https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit) 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.

```swift
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](https://developer.android.com/develop/ui/compose/migrate/interoperability-apis/views-in-compose) 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:

```kotlin
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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mapsindoors.com/academy/mobile-sdks/integrating-mapsindoors-sdks-with-modern-ui-frameworks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
