Issue with selecting alternate route in mapkit
Have you seen this answer yet?
Try setting a maximum polyLine width: 22px, for any zoom level.
“ This code detects touches on poly lines with a maximum distance of 22 pixels in every zoom level. Just point your UITapGestureRecognizer to handleTap:”
How to detect taps on MKPolylines/Overlays like Maps.app?
Detecting touches on MKOverlay in iOS7 (MKOverlayRenderer)
I've done it.
Thanks to incanus and Anna!
Basically I add a TapGestureRecognizer to the MapView, convert the point tapped to map coordinates, go through my overlays and check with CGPathContainsPoint.
Adding TapGestureRecognizer. I did that trick of adding a second double tap gesture, so that the single tap gesture isn't fired when doing a double tap to zoom on map. If anyone knows a better way, I'm glad to hear!
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapTap:)];
tap.cancelsTouchesInView = NO;
tap.numberOfTapsRequired = 1;
UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] init];
tap2.cancelsTouchesInView = NO;
tap2.numberOfTapsRequired = 2;
[self.mapView addGestureRecognizer:tap2];
[self.mapView addGestureRecognizer:tap];
[tap requireGestureRecognizerToFail:tap2]; // Ignore single tap if the user actually double taps
Then, on the tap handler:
-(void)handleMapTap:(UIGestureRecognizer*)tap{
CGPoint tapPoint = [tap locationInView:self.mapView];
CLLocationCoordinate2D tapCoord = [self.mapView convertPoint:tapPoint toCoordinateFromView:self.mapView];
MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoord);
CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
for (id<MKOverlay> overlay in self.mapView.overlays) {
if([overlay isKindOfClass:[MKPolygon class]]){
MKPolygon *polygon = (MKPolygon*) overlay;
CGMutablePathRef mpr = CGPathCreateMutable();
MKMapPoint *polygonPoints = polygon.points;
for (int p=0; p < polygon.pointCount; p++){
MKMapPoint mp = polygonPoints[p];
if (p == 0)
CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
else
CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
}
if(CGPathContainsPoint(mpr , NULL, mapPointAsCGP, FALSE)){
// ... found it!
}
CGPathRelease(mpr);
}
}
}
I could ask for the MKPolygonRenderer which already has the "path" property and use it, but for some reason it is always nil. I did read someone saying that I could call invalidatePath on the renderer and it does fill the path property but it just seems wrong as the point is never found inside any of the polygons. That is why I rebuild the path from the points. This way I don't even need the renderer and just make use of the MKPolygon object.
Touch events on MKMapView's overlays
Just in case it might help some of you...
I couldn't find a way to do that but I added an annotation on my overlays (Anyway, i needed to do that to display some information) and then I could get the touch event on this annotation. I know it is not the best way to do it but in my situation, and maybe yours, it works ;) !
How can I make map route instructions clickable on SwiftUI?
Yes, but you have to stop throwing away the data. MKRoute.Steps
actually gives you all of the information you need, so first, set up RouteSteps
to accept MKRoute.Steps
:
struct RouteSteps: Identifiable {
let id = UUID()
let step: MKRoute.Step
}
Then, in your 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) } )
}
})
...
}
Then in the main part of your 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)
}
}
...
}
Alternative routes on MKDirections
Here are some "straightforward and easy" ways to do what you describe:
"How to draw the alternative routes on a different color": Since
MKDirections
doesn't seem to use thesubtitle
property of the overlays it creates, you could stuff a "color code" in there before adding the overlay and then inrendererForOverlay
, set the color of the polyline based on itssubtitle
.However, as @matt commented and answered, a better approach is to subclass
MKPolyline
and create an explicitcolor
property."Touch each route": Detecting a touch on a route is more difficult. This answer by @Jensemann works well.
"Change colour when I touch each route": Changing the color once a route is touched can be done by removing that overlay, changing its "color code", then adding the overlay back. Another option here is to create a custom overlay view (renderer in iOS 7) whose color can be dynamically changed.
Polyline Tap in Google Maps
You can use isTappable
property of GMSPolyline.
isTappable
If this overlay should cause tap notifications.
polyline.isTappable = true
Whenever the polyline is tapped, the GMSMapViewDelegate method didTapOverlay is called
func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) {
//Write your code here
}
For further information refer https://developers.google.com/maps/documentation/ios-sdk/reference/protocol_g_m_s_map_view_delegate-p.html#a3a2bf2ff4481528f931183cb364c0f4b
Related Topics
Xcode Won't Let to Build for Device After Denying Codesign to Access Keychain
"The Data Couldn't Be Read Because It Is Missing" Error When Decoding JSON in Swift
iOS Present Modal View Controller on Startup Without Flash
Native Facebook Login Stopped Working After Sdk Update to 3.14
How to Extract a Url from a Sentence That Is in a Nsstring
Xcode 9.2 Upload to App Store Fails with Description Length and Invalid Toolchain Errors
Cllocationmanager Delegate Methods Are Not Getting Called(Google Maps Is Integrated)
How to Show Uipickerview When Selecting Uitextfield
When to Use Uicollectionview Instead of Uitableview
iOS - Uiimagewritetosavedphotosalbum
App Crashes Only on Testflight Build
App Transport Security Xcode 7 Beta 6
How to Cache Using Nsurlsession and Nsurlcache. Not Working
How to Know If an Emoji Is Supported in iOS
Adjust Font Size of Text to Fit in Uibutton
Why I Couldn't Assign Fetched Values from Firestore to an Array in Swift
Alternative Ways to Push View Controllers with Storyboard Programmatically