Hi, I'm trying to mimic same behaviour of the Apple Maps app search button tapped zoom out functionality but I'm not able to do it.
In the Apple Maps app, after searching a place and tapping on the search result item it shows all search result item annotations while zooming out and both shows user's current location (blue dot) and the result annotations.
In my case, I have 2 POI buttons like a tabbar item and when the user tapped in them it passes query string to MKLocalSearch and showing the results through of it. What I want is, when the tabbar item like buttons tapped I have to zoom out on the both results and the user's current location (blue dot).
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)) // I tried setting new MKCoordinateSpan values and change the cameraPosition = .region(with the new 'region')
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
}
}
}