Skip to content

Commit 6d215bf

Browse files
committed
Add Map with coordinate regions and markers
1 parent 6832bb5 commit 6d215bf

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

  • AndroidSwiftUICore/Sources/AndroidSwiftUICore/Primitives
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//
2+
// Map.swift
3+
// AndroidSwiftUICore
4+
//
5+
// A map showing a coordinate region with markers. The interpreter renders a
6+
// schematic map — markers positioned proportionally within the visible
7+
// region — until a tile provider is registered through the composable
8+
// registry (real tiles need a maps SDK and API key on Android).
9+
//
10+
11+
public struct CLLocationCoordinate2D: Equatable, Sendable {
12+
public var latitude: Double
13+
public var longitude: Double
14+
public init(latitude: Double, longitude: Double) {
15+
self.latitude = latitude
16+
self.longitude = longitude
17+
}
18+
}
19+
20+
public struct MKCoordinateSpan: Equatable, Sendable {
21+
public var latitudeDelta: Double
22+
public var longitudeDelta: Double
23+
public init(latitudeDelta: Double, longitudeDelta: Double) {
24+
self.latitudeDelta = latitudeDelta
25+
self.longitudeDelta = longitudeDelta
26+
}
27+
}
28+
29+
public struct MKCoordinateRegion: Equatable, Sendable {
30+
public var center: CLLocationCoordinate2D
31+
public var span: MKCoordinateSpan
32+
public init(center: CLLocationCoordinate2D, span: MKCoordinateSpan) {
33+
self.center = center
34+
self.span = span
35+
}
36+
}
37+
38+
/// A map annotation: a titled pin at a coordinate.
39+
public struct MapMarker: Sendable {
40+
public var title: String
41+
public var coordinate: CLLocationCoordinate2D
42+
public var tint: Color?
43+
public init(_ title: String, coordinate: CLLocationCoordinate2D, tint: Color? = nil) {
44+
self.title = title
45+
self.coordinate = coordinate
46+
self.tint = tint
47+
}
48+
}
49+
50+
public struct Map: View {
51+
52+
internal let region: Binding<MKCoordinateRegion>
53+
internal let markers: [MapMarker]
54+
55+
public init(coordinateRegion: Binding<MKCoordinateRegion>, markers: [MapMarker] = []) {
56+
self.region = coordinateRegion
57+
self.markers = markers
58+
}
59+
60+
public typealias Body = Never
61+
}
62+
63+
extension Map: PrimitiveView {
64+
public func _render(in context: ResolveContext) -> RenderNode {
65+
let value = region.wrappedValue
66+
let children = markers.enumerated().map { index, marker -> RenderNode in
67+
var props: [String: PropValue] = [
68+
"title": .string(marker.title),
69+
"latitude": .double(marker.coordinate.latitude),
70+
"longitude": .double(marker.coordinate.longitude),
71+
]
72+
if let tint = marker.tint { props["tint"] = tint.propValue }
73+
return RenderNode(type: "MapMarker", id: context.path + "/marker#\(index)", props: props)
74+
}
75+
return RenderNode(
76+
type: "Map",
77+
id: context.path,
78+
props: [
79+
"centerLatitude": .double(value.center.latitude),
80+
"centerLongitude": .double(value.center.longitude),
81+
"spanLatitude": .double(value.span.latitudeDelta),
82+
"spanLongitude": .double(value.span.longitudeDelta),
83+
],
84+
children: children
85+
)
86+
}
87+
}

0 commit comments

Comments
 (0)