簡體   English   中英

如何使 map 路線說明在 SwiftUI 上可點擊?

[英]How can I make map route instructions clickable on SwiftUI?

我有一個簡單的 map,它是用“純”SwiftUI 制作的。有一個搜索欄可以搜索一個地方,當我單擊“開始”按鈕時,它會顯示如何從特定位置到那個地方的說明 go。 它顯示在 map 下方的“輸入目的地”字段中。 我想要做的是,我希望這些說明是可點擊的。 當我單擊每條說明時,它應該放大說明發生的特定位置。 現在它只是一個文本列表。 不使用 UIViewRepresentable 是否可以做到這一點? 我該怎么做?

我試過

.onTapGesture {
                    region.span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta/2, longitudeDelta: region.span.longitudeDelta/2)
                }

但它會在我單擊的每條指令上放大相同的位置。

內容視圖

struct Location: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}

struct RouteSteps: Identifiable {
    let id = UUID()
    let step: String
}
    
struct ContentView: View {
@State private var searchBar: String = ""
    @State private var home = CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081)
    @State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
    @State var routeSteps: [RouteSteps] = [RouteSteps(step: "Enter a destination")]
    @State var annotations = [Location(name: "Ankara", coordinate: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081))]
    var body: some View {
        VStack{
             HStack {
            TextField("", text: $searchBar)
            Button("Go") {
                findNewLocation()
            }
            .frame(width: 35, height: 35)
            .foregroundColor(Color.white)
            .background(Color.blue)
            .cornerRadius(5)
             }.textFieldStyle(.roundedBorder).colorInvert()
            Map(coordinateRegion: $region, annotationItems: annotations){ item in
                MapMarker(coordinate: item.coordinate)
            }.frame(width: 400, height: 300)
            List(routeSteps) { r in
                Text(r.step)
            }

ContentView 中的路由 function

func findNewLocation(){
    let searchResult = searchBar
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(searchResult, completionHandler:
    {(placemarks, error) -> Void in
        if((error) != nil){
            print("error at geocode")
        }
        if let placemark = placemarks?.first {
            let coordinates : CLLocationCoordinate2D = placemark.location!.coordinate
            region = MKCoordinateRegion(center: coordinates, span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
            annotations.append(Location(name: placemark.name!, coordinate: coordinates))
            let request = MKDirections.Request()
            request.source = MKMapItem(placemark: MKPlacemark(coordinate: home, addressDictionary: nil))
            request.destination = MKMapItem(placemark: MKPlacemark(coordinate: coordinates, addressDictionary: nil))
            request.requestsAlternateRoutes = false 
            request.transportType = .automobile 
    
            let directions = MKDirections(request: request)
            directions.calculate(completionHandler: { response, error in
                for route in (response?.routes)! {
                    self.routeSteps = []
                    for step in route.steps {
                        self.routeSteps.append(RouteSteps(step: step.instructions))
                    }
                }
            })
        }
    })
}

是的,但你必須停止丟棄數據。 MKRoute.Steps實際上為您提供了所需的所有信息,因此首先設置RouteSteps以接受MKRoute.Steps

struct RouteSteps: Identifiable {
    let id = UUID()
    let step: MKRoute.Step
}

然后,在您的findNewLocation() function 中:

func findNewLocation(){
    ...
    directions.calculate(completionHandler: { response, error in
                // I used a guard statement to get rid of your force unwrap.
                // NEVER force unwrap in a situation like this.
                // Implement error handling here
                guard let response = response else { return } 
                for route in response.routes {
                    // Map the MKRoute.Steps to your struct
                    self.routeSteps = route.steps.map( { RouteSteps(step: $0) } )
                }
            })
    ...

}

然后在您的ContentView的主要部分:

struct ContentView: View {
    ...

    var body: some View {
        ...
            List(routeSteps) { routeStep in
                // Pull your instructions out here
                Text(routeStep.step.instructions)
                    .onTapGesture {
                        // The MKRoute.Step contains an overlay polyline for MKMapKit.
                        // We can't use that in SwiftUI maps yet, but the polyline contains a
                        // boundingMapRect that we can use to change the region shown on the map
                        // with the MKCoordinateRegion(_ MKMapRect) initializer. Setting the region
                        // to the insturction's polyline boundingMapRect does exactly what you want.
                        region = MKCoordinateRegion(routeStep.step.polyline.boundingMapRect)
                    }
            }
        ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM