Displaying sheet on tap / like .sheet #76
-
Hello! I may have missed this in the documentation / examples but I am unable to determine a method in which I can call the |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
Yes this is not in the documentation, because it doesn't differ from the behaviour when using a normal component like a
Only if you find a solution which works for the normal |
Beta Was this translation helpful? Give feedback.
-
Nevertheless, because today I had the time here is some sample code. For anyone reading this: This is the only time im going to provide basic SwiftUI support, because I think this is an often asked question and the solution isn't that easy. You will need the following code for your map: internal struct MapView: UIViewRepresentable {
@Binding internal var mapView: MKMapView
@Binding internal var annotations: [MKPointAnnotation]
internal let didSelectAction: (MKAnnotationView) -> Void
internal let didDeselectAction: (MKAnnotationView) -> Void
internal func makeCoordinator() -> MapCoordinator {
MapCoordinator(self)
}
internal func makeUIView(context: Context) -> MKMapView {
mapView.delegate = context.coordinator
if mapView.showsUserLocation ? (mapView.annotations.count - 1 != self.annotations.count) : (mapView.annotations.count != self.annotations.count) {
DispatchQueue.main.async {
mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotations(self.annotations)
}
}
return mapView
}
internal func updateUIView(_ uiView: MKMapView, context: Context) {
if uiView.showsUserLocation ? (uiView.annotations.count - 1 != self.annotations.count) : (uiView.annotations.count != self.annotations.count) {
DispatchQueue.main.async {
uiView.removeAnnotations(uiView.annotations)
uiView.addAnnotations(self.annotations)
}
}
}
internal class MapCoordinator: NSObject, MKMapViewDelegate {
private var parent: MapView
internal func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard (view.annotation as? MKPointAnnotation) != nil else { return }
self.parent.didSelectAction(view)
}
internal func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
guard (view.annotation as? MKPointAnnotation) != nil else { return }
self.parent.didDeselectAction(view)
}
internal init(_ mapView: MapView) {
self.parent = mapView
}
}
} The following code for your ContentViewModel: internal class ContentViewModel: ObservableObject {
@Published internal var mapView: MKMapView = MKMapView()
@Published internal var annotations: [MKPointAnnotation] = []
@Published internal var annotation: MKPointAnnotation? = nil
@Published internal var bottomSheetPosition = .hidden
//Use this function for opening the BottomSheet (from a list or something); the according MapAnnotation gets automatically selected
internal func openBottomSheetView(for annotation: MKPointAnnotation) -> Void {
self.selectAnnotation(for: annotation)
}
//Use this function for closing the BottomSheet
internal func closeBottomSheetView() -> Void {
self.deselectAnnotation()
}
private func selectAnnotation(for annotation: MKPointAnnotation) -> Void {
self.mapView.selectAnnotation(annotation, animated: true)
let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
self.mapView.setRegion(region, animated: true)
}
private func deselectAnnotation() -> Void {
self.mapView.deselectAnnotation(self.annotation, animated: true)
}
internal func didSelectAction(view: MKAnnotationView) -> Void {
self.annotation = (view.annotation as? MKPointAnnotation)
self.bottomSheetPosition = .middle
}
internal func didDeselectAction(view: MKAnnotationView) -> Void {
self.annotation = nil
self.bottomSheetPosition = .hidden
}
} And finally here your ContentView: struct ContentView: View {
@StateObject private var contentViewModel: ContentViewModel = ContentViewModel()
var body: some View {
//MapView
MapView(mapView: self.$contentViewModel.mapView, annotations: self.$contentViewModel.annotations, didSelectAction: self.contentViewModel.didSelectAction, didDeselectAction: self.contentViewModel.didDeselectAction)
.edgesIgnoringSafeArea(.all)
.bottomSheet(bottomSheetPosition: self.$contentViewModel.bottomSheetPosition, options: [], title: nil) {
Text("My Map Annotation Bottom Sheet")
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Over complicated, can't you just add a binding bool flag please?
|
Beta Was this translation helpful? Give feedback.
-
No. The standout feature for my library is that it can have multiple states. If you just want one state, please look for another library. Nevertheless I think you didn’t understood my initial answer aka the orginial question, because even when using a library, which offers |
Beta Was this translation helpful? Give feedback.
Nevertheless, because today I had the time here is some sample code. For anyone reading this: This is the only time im going to provide basic SwiftUI support, because I think this is an often asked question and the solution isn't that easy.
You will need the following code for your map: