Disable Google Map Movement on double tap in iOS - ios

I am using the Google Maps SDK for my iOS App.
You can zoom in on the map using either of two gestures.
Double Tap
Double Tap -> Hold -> Drag Down
In the first way, the map zooms in, but the map shifts near to the position where I double tap.
While in the second method, the map zooms in staying at the current map centre.
I want to achieve the second type of behaviour(map staying on current centre rather than shifting) on the first gesture too. How do I go about it?
EDIT: Basically the behaviour should be same as the Official Google Map Double Tap.

This is a config item in GMSUISettings class, so you can access it on your GMSMapView object's 'settings' property like below,
Obj-C:
mapView.settings.allowScrollGesturesDuringRotateOrZoom = NO;
Swift 2.1:
mapView.settings.allowScrollGesturesDuringRotateOrZoom = false
I had to dig into their source code to find this config item, its not mentioned anywhere in the docs.

You can disable the default gestures on the map by setting properties of the GMSUISettings class, which is available as a property of the GMSMapView. The following gestures can be enabled and disabled programmatically. Note disabling the gesture will not limit programmatic access to the camera settings.
scrollGestures — controls whether scroll gestures are enabled or disabled. If enabled, users may swipe to pan the camera.
zoomGestures — controls whether zoom gestures are enabled or disabled. If enabled, users may double tap, two-finger tap, or pinch to zoom the camera. Note that double tapping may pan the camera to the specified point.
tiltGestures — controls whether tilt gestures are enabled or disabled. If enabled, users may use a two-finger vertical down or up swipe to tilt the camera.
rotateGestures — controls whether rotate gestures are enabled or disabled. If enabled, users may use a two-finger rotate gesture to rotate the camera.
In the below example, both pan and zoom gestures have been disabled.
(void)loadView {
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:1.285
longitude:103.848
zoom:12];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView_.settings.scrollGestures = NO;
mapView_.settings.zoomGestures = NO;
self.view = mapView_;
}

Related

Swift - GoogleMaps SDK get single or double finger tap gestures

I am using Google Maps SDK in my project. I want to check and detect when tap on google map that is used single finger or double finger ?
My requirement is, disable single finger use and enable double finger use. I want all Gestures work on double finger not on single finger.
First, disable all gesture on your GMSMapView instance. Documentation says:
You can disable the default gestures on the map by setting properties of the GMSUISettings class, which is available as a property of the GMSMapView
Source: https://developers.google.com/maps/documentation/ios-sdk/controls
Then you may be able to add some UITapGestureRecognizer:
Source: https://developer.apple.com/documentation/uikit/uitapgesturerecognizer
Don't forget to set numberOfTouchesRequired to 2 !
Source: https://developer.apple.com/documentation/uikit/uitapgesturerecognizer/1623580-numberoftouchesrequired

How do I intercept mapview panning and zooming (Swift 4)

I'm trying to restrict panning and zooming for a mapview, to remain within a predefined max and min camera altitude and the four corners of a bounding box.
The solutions proposed here, allow the user to pan outside the region, and then use regionDidChangeAnimated to pan them back to within the pre-defined bounds.
I'd like to know if it's possible to just never allow the user to pan outside the bounds in the first place. Can I, for example, intercept panning/zooming gestures and decide whether or not to let them continue?
I think I'm looking for something like the following pseudocode:
func blockMapViewPanEvent(_ mapView: MKMapView){
return mapView.visibleMapRect.isContainedWithin(topLeft, bottomRight)
}
I know that MapBox's Swift SDK achieves this, so I imagine it's possible. Can I do this with plain-old MapKit?
Edit for Clarity:
I want to restrict panning and zooming so the user can pan and zoom as much as they want within a bounding box. For example, if the bounding box is of Germany, I want the user to be able to pan and zoom within Germany, but they should never be able to see Spain, since Spain is outside the bounding box of Germany.
I do not want to disable all user interaction on the map view.
If I am understanding you correctly, you want to disable user interaction in the map.
Here are the few options available in map view. These might be helpful for you
mapView.zoomEnabled = false
mapView.scrollEnabled = false
mapView.userInteractionEnabled = false
If you have issues with these you can simply put a transparent view over map view
MapKit now makes this possible in iOS 13
You can restrict panning with:
let boundaryRegion = MKCoordinateRegion(...) // the region you want to restrict
let cameraBoundary = CameraBoundary(region: boundaryRegion)
mapView.setCameraBoundary(cameraBoundary: cameraBoundary, animated: true)
And prevent the user zooming outside your region of interest with:
let zoomRange = CameraZoomRange(minCenterCoordinateDistance: 100,
maxCenterCoordinateDistance: 500)
mapView.setCameraZoomRange(zoomRange, animated: true)
There are some limitations that you can best see in the WWDC 2019 video at 2378 seconds.
References
MapKit documentation on "Constraining the Map View"
class reference for MKMapView.CameraBoundary
class reference for MKMapView.CameraZoomRange

Disabling double tap to zoom in Google Maps for iOS?

I'm working on an app (iOS 7) which is using Google Maps (v1.8.1). I'm trying to implement a feature, where You would have a polygon in the map, and when you double tap it - it zooms to the polygon. I've read around that I could disable zooming gestures in the map, via googleMapView.settings.zoomGestures = NO;, but I don't want to lose zoomGestures at all (You can zoom in using double tap (when not double tapping on the polygon) or pinch to zoom). I've tried adding a GestureRecognizer, but the method for the recognizer gets called after the zoom happens (GMSMapViewDelegate method willMove gets called first). How would I go about this?

Disable all user interaction for MKMapView except for a given MKAnnotationView

I have a MKMapView and a few MKAnnotationViews on my map.
When a certain event happens, I would like to disable user interaction on my MKMapView but leave interaction on my MKAnnotationView available.
Ideally, it would be
self.mapView.userInteraction = NO;
self.myAnnotationView.userInteraction = YES;
Printing
[self.mapView recursiveDescription]
I have found that my annotation view is nested in MKNewAnnotationContainerView which doesn't have a publicly exposed property on Apple's class reference.
Any ideas?
On the mapView, set scrollEnabled, zoomEnabled, pitchEnabled, and rotateEnabled to NO and leave userInteractionEnabled as YES.
This way, the annotation views will still be enabled.
For pitchEnabled and rotateEnabled, you may want to check if those properties exist before setting them (eg. check if the map view respondsToSelector:#selector(setPitchEnabled), etc.) since they were added in iOS 7.

Intercept touches on UIView over GMSMapView

I'm trying to overlay a UIView over a google GMSMapView. The goal is to intercept swipes in order to know when the map is being moved manually. (I know I could check -mapView:willMove: but that gets called regardless of whether the map is moving programmatically or as result of manual touch). I'm programmatically re-centering the map as the position updates--because Google doesn't do it for you like Apple does. Like every map program out there, I want to stop centering on the current position as soon as the user manually moves the map. The only way I can think to capture that occurrence (short of switching to mapkit or waiting for Google to add to the API) is to capture a swipe as it's going past a view laid over the map.
To clarify, my question is how do I lay a view over a google map, make it respond to a swipe and still allow that event to pass through to the GMSMapView?
Both my map and interceptView are sibling children of the main view. interceptView has a gestureRecognizer, is set to opaque, not hidden and userInteractionEnabled = YES. As such the interceptView picks up touch events just fine. But the map underneath doesn't move. If I set interceptView.userInteractionEnabled = NO, the map works fine.
"Passing touches" by overriding touchesBegan and calling GMSMapView's touchesBegan doesn't do anything. And overriding hitTest doesn't seem to be an option because I can't subclass GMSMapView. Has anyone done this? I know there's a lot on here about passing particular events through. I want to process a particular event on two views, one of which is Google's map layer which I can't modify the code of.
mapView:willMove: receives a bool "gesture" which is true if the move was triggered by a user gesture and false if it wasn't. So you can stop re-centering the map only if "gesture" is true. That way you can be sure that the map is being moved manually.
Here is a delegate method check it
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate;
You can intercepte the tap using the GMSMapViewDelegete and implementing this method:
-(void)panoramaView:(GMSPanoramaView *)panoramaView didTap:(CGPoint)point;
Example:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
CLLocationCoordinate2D panoramaNear = {latitudine,longitudine};
GMSPanoramaView *panoView = [GMSPanoramaView panoramaWithFrame:CGRectZero
nearCoordinate:panoramaNear];
[panoView setDelegate:self];
self.view = panoView;
}
-(void)panoramaView:(GMSPanoramaView *)panoramaView didTap:(CGPoint)point{
NSLog(#"Tap");
}

Resources