如何在SwiftUI的新地图视图中创建可点击的图钉?

时间:2020-08-01 23:49:06

标签: swiftui ios14

我正在使用SwiftUI的新Map视图来显示注释的图钉,并且希望在单击图钉时显示视图以编辑注释的名称和描述。

我尝试将MapAnnotation与包含带有大头针图像的按钮的视图一起使用。图像显示正确,但是按钮不起作用。

是否可以做到这一点而不会退回到MKMapView的UIViewRepresentable?

import SwiftUI
import MapKit

struct ContentView: View {
    @State private var showingEditScreen = false

    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 37.334722,
                                       longitude: -122.008889),
        span: MKCoordinateSpan(latitudeDelta: 1,
                               longitudeDelta: 1)
    )

    @State private var pins: [Pin] = [
        Pin(name: "Apple Park",
            description: "Apple Inc. headquarters",
            coordinate: CLLocationCoordinate2D(latitude: 37.334722,
                                               longitude:-122.008889))
    ]

    var body: some View {
        Map(coordinateRegion: $region,
            interactionModes: .all,
            annotationItems: pins,
            annotationContent: { pin in
                MapAnnotation(coordinate: pin.coordinate,
                              content: {
                                PinButtonView(pin: pin)
                              })
            })
    }
}

我的Pin定义:

struct Pin: Identifiable {
    let id = UUID()
    var name: String
    var description: String
    var coordinate: CLLocationCoordinate2D

}

带有按钮和大头针图像的视图:

struct PinButtonView: View {
    @State private var showingEditScreen = false
    @State var pin: Pin

    var body: some View {
        Button(action: {
            showingEditScreen.toggle()
        }) {
            Image(systemName: "mappin")
                .padding()
                .foregroundColor(.red)
                .font(.title)
        }
        .sheet(isPresented: $showingEditScreen,
               content: {
                EditView(pin: self.$pin)
               })
    }
}

编辑视图:

struct EditView: View {
    @Environment(\.presentationMode) var presentationMode

    @Binding var pin: Pin

    var body: some View {
        NavigationView {
            Form {
                    TextField("Place name", text: $pin.name)

                    TextField("Description", text: $pin.description)
            }
            .navigationTitle("Edit place")
            .navigationBarItems(trailing: Button("Done") {
                self.presentationMode.wrappedValue.dismiss()
            })
        }
    }
}

3 个答案:

答案 0 :(得分:1)

从 XCode 12.3 开始,这似乎可以与按钮一起使用。我注意到的一个关键问题是,如果您使用偏移量,那么您的按钮可能会被放置在注释的可点击区域之外。

为了解决这个问题,您可以添加额外的填充来解决偏移并将其保持在可点击的范围内:

MapAnnotation(coordinate: item.placemark.coordinate) {
  ZStack {
      MapPinView() // My view for showing a precise pin
      VStack { // A prompt with interactive option, offset by 60pt
          Text("Use this location?")
          HStack {
              Button("Yes", action: {
                  print("yes")
              })
              
              Button("No", action: {
                  print("no")
              })
          }
      }
      .offset(x: 0, y: 60) // offset prompt so it's below the marker pin
  }
  .padding(.vertical, 60) // compensate for offset in tappable area of annotation. pad both the top AND the bottom to keep contents centered
}

答案 1 :(得分:0)

我有一个 SwiftUI MapKit 视图,它使用 MapAnnotations 和一个可点击的图钉,并显示一个包含信息的视图。

它并不漂亮,但目前仅适用于 iOS 14。

https://github.com/PhilStollery/BAB-Club-Search/blob/main/Shared/views/AnnotatedMapView.swift

import MapKit
import SwiftUI

struct AnnotatedMapView: View {
    
    @ObservedObject
    private var locationManager = LocationManager()
    
    // Default to center on the UK, zoom to show the whole island
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 54.4609,
                                       longitude: -3.0886),
        span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))
    
    @ObservedObject var store: ClubStore
    
    var body: some View {
        ZStack {
            Map(coordinateRegion: $region,
                showsUserLocation: true,
                annotationItems: store.clubs!) {
                    club in MapAnnotation(coordinate: club.coordinate) {
                        VStack{
                            if club.show {
                                ZStack{
                                    RoundedRectangle(cornerRadius: 10)
                                        .fill(Color(UIColor.systemBackground))
                                        .shadow(radius: 2, x: 2, y: 2)
                                    VStack{
                                        NavigationLink(destination: ClubLocationView(club: club)) {
                                            Text(club.clubname)
                                                .fontWeight(.bold)
                                        }
                                        .padding()
                                        Text(club.association)
                                            .padding(.leading)
                                            .padding(.trailing)
                                        Text(club.town)
                                            .padding(.bottom)
                                    }
                                }
                                .onTapGesture {
                                    let index: Int = store.clubs!.firstIndex(where: {$0.id == club.id})!
                                    store.clubs![index].show = false
                                }
                            } else {
                                Image(systemName: "house.circle")
                                    .font(.title)
                                    .foregroundColor(.accentColor)
                                    .onTapGesture {
                                        let index: Int = store.clubs!.firstIndex(where: {$0.id == club.id})!
                                        store.clubs![index].show = true
                                    }
                            }
                        }
                    }
            }
            .edgesIgnoringSafeArea(.bottom)
        }
        .navigationBarTitle(Text("Map View"), displayMode: .inline)
        .navigationBarItems(trailing:
                                Button(action: {
                                    withAnimation {
                                        self.region.center = locationManager.current!.coordinate
                                        self.region.span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
                                    }
                                })
                                    {Image(systemName: "location")}
        )
    }
}

答案 2 :(得分:-1)

使用Xcode 12 GM地图销钉仍然无法解决。