Reputation: 4054
I'm presenting a mapView via a UIViewRepresentable and want to have an image 'target' in the centre of the map. This image blocks both tap events and panning gestures that start on the image. So dropping an annotation onto the map below the image means that its callout can't be initiated.
I've read about problems with transparency so I remade the target image with the 'clear' area as a white with opacity 1% but no change in behaviour.
Setting allowsHitTesting
to false doesn't work either although if I insert a button below the image (Test 1 in code) I can tap it, just not the map/annotation so there seems to be a difference between the MapKit elements and the SwiftUI views I add myself.
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
ZStack {
MapView()
/*Test 1*/ Button("Tap Me") {
print("Text button was tapped")
}
Image("target")
.frame(width: 90, height: 90)
.allowsHitTesting(false)
/*Test 2*/ Rectangle()
.fill(Color.red.opacity(0.2))
.frame(width: 90, height: 90)
.allowsHitTesting(false)
/*Test 3*/ Button(action: {print("Round button was tapped")}) {
Circle()
.fill(Color.red.opacity(0.2))
.frame(width: 90, height: 90)
}
.allowsHitTesting(false)
.disabled(true)
}
}
}
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
let map = MKMapView()
map.mapType = .standard
map.isRotateEnabled = false
let location = CLLocation(latitude: 40.763783, longitude: -73.973133)
let region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
map.setRegion(region, animated: true)
let annotation = MyAnnotation(coordinate: location.coordinate)
annotation.title = "Title"
annotation.subtitle = "Subtitle"
map.addAnnotation(annotation)
return map
}
func updateUIView(_ uiView: MKMapView, context: Context) {
}
}
class MyAnnotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
init(coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
}
}
Swapping the Image for a Rectangle (Test 2 in code) has the same behaviour, I can interact with Views I add but cannot pass my touches/pans through to the MapKit elements. I even tried using a disabled Button in the hope that its hit testing would be more in line with what I'm trying to achieve. Sadly not.
Does anyone know of a way to interact with the mapView, taps and pans, through another view?
Upvotes: 2
Views: 1294
Reputation: 8091
works if you disable all above...
so button "tap me" works.
struct ContentView: View {
var body: some View {
ZStack {
MapView()
/*Test 1*/ Button("Tap Me") {
print("Text button was tapped")
}
Image("target")
.frame(width: 90, height: 90)
.allowsHitTesting(false)
.allowsHitTesting(false)
.disabled(true)
/*Test 2*/ Rectangle()
.fill(Color.red.opacity(0.2))
.frame(width: 90, height: 90)
.allowsHitTesting(false)
.allowsHitTesting(false)
.disabled(true)
/*Test 3*/ Button(action: {print("Round button was tapped")}) {
Circle()
.fill(Color.red.opacity(0.2))
.frame(width: 90, height: 90)
}
.allowsHitTesting(false)
.disabled(true)
}
}
}
Upvotes: 0
Reputation: 257493
Yes, even transparent images do not allow hit-through so far. In your case, simple enough, the possible approach is to create custom shape, like below. Shapes do pass hits.
Here is simple demo of shape to show the direction.
struct Cross: Shape {
func path(in rect: CGRect) -> Path {
return Path { path in
path.move(to: CGPoint(x: rect.midX, y: 0))
path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
path.move(to: CGPoint(x: 0, y: rect.midY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
path.move(to: CGPoint(x: rect.midX, y: rect.midY))
path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: 10, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 360), clockwise: false)
}
}
}
struct ContentView: View {
var body: some View {
ZStack {
MapView()
Cross().stroke(Color.red)
.frame(width: 90, height: 90)
}
}
}
Upvotes: 2