Appearance
Mobile App Integration
Embed Layota maps in your iOS and Android apps using the native SDKs.
iOS (Swift)
Installation
The iOS SDK is distributed as a Swift package (source distribution for now) — see the iOS SDK installation instructions.
UIKit Integration
swift
import UIKit
import LayotaMapSDK
class MapViewController: UIViewController {
let mapView = LayotaMapView(options: LayotaMapOptions(
projectId: "your-project-id",
apiKey: "sk_..."
))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(mapView)
mapView.frame = view.bounds
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.map.on(.areaClick) { event in
if case .areaClick(let area) = event {
self.showDetail(for: area)
}
}
Task {
try await mapView.map.ready()
}
}
func showDetail(for area: Area) {
let alert = UIAlertController(title: area.title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}SwiftUI Integration
swift
import SwiftUI
import LayotaMapSDK
struct MapScreen: View {
@State private var map: LayotaMap?
@State private var selectedArea: Area?
var body: some View {
VStack {
LayotaMapSwiftUI(
options: LayotaMapOptions(
projectId: "your-project-id",
apiKey: "sk_..."
),
map: $map
)
.ignoresSafeArea()
if let area = selectedArea {
Text(area.title)
.font(.headline)
.padding()
}
}
.task {
map?.on(.areaClick) { event in
if case .areaClick(let area) = event {
selectedArea = area
}
}
}
}
}Android (Kotlin)
Installation
The Android SDK is distributed as a Gradle library module (source distribution for now) — see the Android SDK installation instructions.
XML Layout Integration
kotlin
class MapActivity : AppCompatActivity() {
private lateinit var mapView: LayotaMapView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map)
mapView = findViewById(R.id.map_view)
mapView.initialize(LayotaMapOptions(
projectId = "your-project-id",
apiKey = "sk_..."
))
mapView.map?.on(SdkEventType.AREA_CLICK) { event ->
if (event is LayotaEvent.AreaClick) {
showDetail(event.area)
}
}
lifecycleScope.launch {
mapView.map?.ready()
}
}
private fun showDetail(area: Area) {
AlertDialog.Builder(this)
.setTitle(area.title)
.setPositiveButton("OK", null)
.show()
}
}Jetpack Compose Integration
kotlin
@Composable
fun MapScreen() {
var map by remember { mutableStateOf<LayotaMap?>(null) }
var selectedArea by remember { mutableStateOf<Area?>(null) }
Column(modifier = Modifier.fillMaxSize()) {
LayotaMapCompose(
options = LayotaMapOptions(
projectId = "your-project-id",
apiKey = "sk_..."
),
modifier = Modifier.weight(1f),
onMapReady = { map = it }
)
selectedArea?.let { area ->
Text(
text = area.title,
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(16.dp)
)
}
}
LaunchedEffect(map) {
map?.on(SdkEventType.AREA_CLICK) { event ->
if (event is LayotaEvent.AreaClick) {
selectedArea = event.area
}
}
map?.ready()
}
}Common Patterns
Deep Linking to an Area
Open the map focused on a specific area:
swift
let options = LayotaMapOptions(
projectId: "your-project-id",
areaId: "coffee-shop", // focus on load
levelId: "floor-1" // start on this level
)kotlin
val options = LayotaMapOptions(
projectId = "your-project-id",
areaId = "coffee-shop",
levelId = "floor-1"
)Building a Route
swift
let from = RouteEntity(id: "entrance", type: .area, levelId: "floor-1")
let to = RouteEntity(id: "cafe", type: .area, levelId: "floor-2")
map.buildRoute(from: from, to: to)kotlin
val from = RouteEntity("entrance", RouteEntity.EntityType.AREA, "floor-1")
val to = RouteEntity("cafe", RouteEntity.EntityType.AREA, "floor-2")
map.buildRoute(from, to)Cleanup
Always destroy the map when leaving the screen to free WebView resources:
- iOS UIKit: Call
map.destroy()inviewDidDisappearordeinit - iOS SwiftUI: Handled automatically by
LayotaMapSwiftUI - Android View: Handled automatically when
LayotaMapViewis detached - Android Compose: Handled automatically via
DisposableEffect