【问题标题】:SwiftUI Views blocking touches to MapKit but not other viewsSwiftUI 视图阻止了对 MapKit 的触摸,但不阻止其他视图
【发布时间】:2020-08-01 19:44:45
【问题描述】:

我正在通过 UIViewRepresentable 呈现 mapView,并希望在地图中心有一个图像“目标”。此图像会阻止在图像上开始的点击事件和平移手势。因此,将注释放到图像下方的地图上意味着无法启动其标注。

我已阅读有关透明度问题的信息,因此我将目标图像的“透明”区域重新制作为不透明度为 1% 但行为没有变化的白色。

allowsHitTesting 设置为 false 也不起作用,尽管如果我在图像下方插入一个按钮(代码中的测试 1)我可以点击它,而不是地图/注释,因此 MapKit 之间似乎存在差异元素和我自己添加的 SwiftUI 视图。

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
    }
}

将图像交换为矩形(代码中的测试 2)具有相同的行为,我可以与添加的视图交互,但不能将触摸/平移传递给 MapKit 元素。我什至尝试使用禁用的按钮,希望它的命中测试更符合我想要实现的目标。可惜没有。

有谁知道通过另一个视图与 mapView、点击和平移交互的方法?

【问题讨论】:

    标签: swift swiftui mapkit gesture touches


    【解决方案1】:

    是的,到目前为止,即使是透明图像也不允许点击。在您的情况下,很简单,可能的方法是创建自定义形状,如下所示。形状确实会通过命中。

    这是显示方向的简单形状演示。

    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)
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果您禁用以上所有功能...

      所以“点击我”按钮有效。

      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)
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-02
        • 2012-08-07
        相关资源
        最近更新 更多