iOS 17 MapKit SwiftUI - 选择按钮时缩小

问题描述 投票:0回答:1

我试图模仿苹果地图应用程序搜索按钮点击缩小功能的相同行为,但我无法做到这一点。

在Apple地图应用程序中,搜索地点并点击搜索结果项目后,它会在缩小时显示所有搜索结果项目注释,并显示用户当前位置(蓝点)和结果注释。

就我而言,我有 2 个 POI 按钮(如选项卡栏项目),当用户点击它们时,它会将查询字符串传递给 MKLocalSearch 并通过它显示结果。我想要的是,当点击按钮等选项卡栏项目时,我必须缩小结果和用户当前位置(蓝点)。

import SwiftUI
import MapKit

   struct ContentView: View {

    @State private var cameraPosition: MapCameraPosition = .userLocation(followsHeading: true, fallback: .automatic)
    @State private var visibleRegion: MKCoordinateRegion?
    @State private var searchResults: [MKMapItem] = []
    @State private var selectedResult: MKMapItem?
    @State private var route: MKRoute?
    @State var isShowingBottomSheet = false
    @StateObject var locationManager = LocationManager.shared

    var body: some View {
        if locationManager.state == .notDetermined {
            LocationRequestView()
        } else if locationManager.state == .denied {
            LocationRequestDeniedView()
        } else {
            Map(position: $cameraPosition, selection: $selectedResult) {
                Annotation("Current location", coordinate: .userLocation) {

                }
                .annotationTitles(.hidden)

                ForEach(searchResults, id:\.self) {
                    Marker(item: $0)
                }
                .annotationTitles(.hidden)

                if let route {
                    MapPolyline(route)
                        .stroke(.blue, lineWidth: 5)
                }
            }
            .mapStyle(.standard(elevation: .realistic))
            .safeAreaInset(edge: .bottom) {
                HStack {
                    Spacer()
                    VStack(spacing: 0) {
                        if let selectedResult {
                            ItemInfoView(isShowing: $isShowingBottomSheet, route: $route, selectedTabBarButton: selectedTabBarButton, selectedResult: selectedResult, url: self.shareLocation())
                                .frame(height: 480)
                                .clipShape(RoundedRectangle(cornerRadius: 10))
                                .padding([.top, .horizontal])
                                .presentationContentInteraction(.scrolls)
                        }

                        Divider()

                        POIButtons(
                            position: $cameraPosition,
                            searchResults: $searchResults,
                            selectedTabBarButton: $selectedTabBarButton,
                            visibleRegion: visibleRegion
                        )
                            .padding(.top)
                    }

                    Spacer()
                }
                .background(.thinMaterial)
            }
            .onChange(of: searchResults) {
                withAnimation {
                    cameraPosition = .userLocation(followsHeading: true, fallback: .automatic)
                }
            }
            .onChange(of: selectedResult) {
                let region = MKCoordinateRegion(
                center: .userLocation, 
                span: MKCoordinateSpan(
                latitudeDelta: 500, 
                longitudeDelta: 500)) 
                cameraPosition = .region(region)
                getDirections()

                if selectedResult?.pointOfInterestCategory == .evCharger {
                    selectedTabBarButton = "EV"
                } else {
                    selectedTabBarButton = "Gas"
                }
            }
            .onMapCameraChange { context in
                visibleRegion = context.region
            }
            .mapControls {
                MapUserLocationButton()
                MapCompass()
                MapScaleView()
            }
        }
    }

    func getDirections() {
        route = nil
        isShowingBottomSheet = true
        guard let selectedResult else { return }

        let location = locationManager.manager.location
        guard let coordinate = location?.coordinate else { return }

        let request = MKDirections.Request ()
        request.source = MKMapItem(placemark: MKPlacemark (coordinate: coordinate))
        request.destination = selectedResult
        Task {
            let directions = MKDirections(request: request)
            let response = try? await directions.calculate()
            route = response?.routes.first
        }
    }
}

我尝试设置新的 MKCooperativeSpan 值并更改

cameraPosition = .region(with the new 'region')

swiftui mapkit ios17
1个回答
0
投票

这就是我为解决方案所做的;

简单来说,以下方法直接通过

coordinates: [CLLocationCoordinate2D]
计算最小和最大纬度和经度值,然后使用搜索结果计算
MKCoordinateRegion
的中心和跨度(在我的例子中,搜索功能是点击 EV 或 Gas Station 选项卡栏)纽扣)。我更新了上面ContentView中计算方法的用法。

func calculateRegionToFit(coordinates: [CLLocationCoordinate2D]) -> MKCoordinateRegion? {
    // First check if the coordinates array is empty
    guard !coordinates.isEmpty else {
        return nil
    }

    // Find the minimum and maximum latitude and longitude values of the search
    var minLat = coordinates[0].latitude
    var maxLat = coordinates[0].latitude
    var minLon = coordinates[0].longitude
    var maxLon = coordinates[0].longitude

    for coordinate in coordinates {
        minLat = min(minLat, coordinate.latitude)
        maxLat = max(maxLat, coordinate.latitude)
        minLon = min(minLon, coordinate.longitude)
        maxLon = max(maxLon, coordinate.longitude)
    }

    // Calculate the region based on the search values
    let center = CLLocationCoordinate2D(latitude: (minLat + maxLat) / 2, longitude: (minLon + maxLon) / 2)
    let span = MKCoordinateSpan(
        latitudeDelta: maxLat - minLat,
        longitudeDelta: maxLon - minLon
    )
    let region = MKCoordinateRegion(center: center, span: span)
    return region
}
© www.soinside.com 2019 - 2024. All rights reserved.