Google Maps SDK iOS - prevent map from changing location on zoom - ios

I have a problem that I can't solve for some time.
I have a GMSMapView with imageView in front of it in the center. In result - I can drag map and always have centered pin. But problems come when I zoom the map.
On zooming - position of map target changes and my imageView points to another location.
I can detect if zoom changed, but I cant actually force GMSMapView to do ONLY zoom without any location changing.
-(void) mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position
{
if (mZoomLevel != mapView.camera.zoom)
{
mZoomLevel = mapView.camera.zoom;
}
}
So basically, I want to have always centered pin, even if I perform zoom.
I tried GMSMarker - but it has problems with performance when following map center. It doesn't do it instantly, so I decided to use imageView.
Main question: how to lock current location of the map while performing zoom?

Google fixed this issue with google maps sdk 1.10.0.
The solution is to simply add this line when configuring GMSMapview:
_mapView.settings.allowScrollGesturesDuringRotateOrZoom = NO;

Well, after 10 days of going back to this problem, I finally solved it!
The answer was pretty easy!
Few steps here:
1. Add imageView as marker on top of the GMSMapView
2. Add UIPanGestureRecognizer to the GMSMapView (don't forget to set delegate, it is important)
3. Then use this code:
- (void) didPan:(UIPanGestureRecognizer*) gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
_mapView.settings.scrollGestures = true;
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if (gestureRecognizer.numberOfTouches > 1)
{
_mapView.settings.scrollGestures = false;
}
else
{
_mapView.settings.scrollGestures = true;
}
return true;
}

Swift 3:
mapView.settings.scrollGestures = false

Related

compass image rotate as here map

Map Orientation works as this code. But compass image is not rotate as per map rotate. Please help how to make compass as here map
- (void)mapView:(NMAMapView *)mapView didReceiveRotation:(float)rotation atLocation:(CGPoint)location
{
[self.mapView setOrientation:180 withAnimation:NMAMapAnimationLinear];
_comPassImg.transform =CGAffineTransformMakeRotation(rotation);//not working smoothly
}
You can listen to NMAMapView::NMAMapEvent::NMAMapEventOrientationChanged instead, e.g.:
[mapView respondToEvents:NMAMapEventOrientationChanged withBlock:^BOOL (NMAMapEvent event, NMAMapView *mapView, id eventData) {
_comPassImg.transform = CGAffineTransformMakeRotation(mapView.orientation);
return YES;
}];
You can also try NMAOrientableMapMarker to see if that works for you.

How to add dragging option to SKAnnotaion?

I have a feature to place an annotation to a map by performing a long press at a point on the map. Then user can move the annotation to other position by dragging.
I was able to achieve that using RouteMe, but now I want to replace RouteMe with Skobbler.
Is there any property to enable dragging for annotations/markers on map using Skobbler? If yes, please help me achieve it.
Don't you wan't to do this :
Setting the annotation delegate, then
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
coordinate = newCoordinate;
if (self.delegate respondsToSelector:#selector(mapAnnotationCoordinateHaveChanged))
[self.delegate performSelector(#selector(mapAnnotationCoordinateHaveChanged))];
}
In your delegate :
- (void) mapAnnotationCoordinateHaveChanged{
//some coordinates update code
}

iOS detect drag outside left edge of screen

In iPad when you put your finger outside top or bottom edge of screen and then drag it on screen a menu is revealed. How can I implement that?
There is specifically a Gesture Recogniser class for this, introduced in iOS 7. It's the UIScreenEdgePanGestureRecognizer. The documentation for it is here. Check it out.
To test this in the simulator, just start the drag from near the edge (~15 points).
Also, you will have to create a gestureRecognizer for each edge. You can't OR edges together, so UIRectEdgeAll won't work.
There is a simple example here. Hope this helps!
Well you can do something like this, this example is the case where you want you pan gesture to work only when the user swipes 20px inside from the right hand side of the screen
First of all add the gesture to your window
- (void)addGestures {
if (!_panGesture) {
_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[_panGesture setDelegate:self];
[self.view addGestureRecognizer:_panGesture];
}
}
After adding the check whether the touch you recieved is a pan gesture and then perform your action accordingly
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint point = [touch locationInView:self.view];
if (gestureRecognizer == _panGesture) {
return [self slideMenuForGestureRecognizer:gestureRecognizer withTouchPoint:point];
}
return YES;
}
Here is how you can check whether your touch is contained in the region where you want it to be
-(BOOL)isPointContainedWithinBezelRect:(CGPoint)point {
CGRect leftBezelRect;
CGRect tempRect;
//this will be the width between CGRectMaxXEdge and the screen offset, thus identifying teh region
CGFloat bezelWidth =20.0;
CGRectDivide(self.view.bounds, &leftBezelRect, &tempRect, bezelWidth, CGRectMaxXEdge);
return CGRectContainsPoint(leftBezelRect, point);
}

Mapbox annotation layer rotation resets on map zoom or move

I'm trying to customize the appearance of the layers of my annotations in mapbox.
I want to rotate every annotation layer.
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation
{
if (annotation.isUserLocationAnnotation)
return nil;
RMMarker *marker;
CGPoint xy = CGPointFromString(annotation.userInfo);
marker = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:#"arrow.png"]];
marker.transform = CATransform3DMakeRotation(atan2f(xy.x, xy.y) * 180 / M_PI,0,0,1);
marker.canShowCallout = YES;
return marker;
}
It works the first time they load on the map. But when I move or zoom the map they reset back to their initial transform identity matrix.
Any ideas how I could solve this ? Or is it a bug of mapbox ?
Take a look in RMMapView.m at the annotationTransform. This gets corrected during movements for things like compass tracking mode, so you'll want to modify things with your own custom transform(s) as this isn't a public API part of this SDK.

Any Workaround to MKUserTrackingModeFollowWithHeading Bug in iOS6?

I'm desperately looking for a workaround to the well documented bug in MapKit in iOS6 that makes MKUserTrackingModeFollowWithHeading effectively unusable at higher magnifications:
There is a very simple example project [here].(https://dl.dropboxusercontent.com/u/316978/MapKitBug.zip)
Steps to reproduce:
Tap the MKUserTrackingModeButton to zoom in to your location.
Tap to zoom in closer 2 or 3 times.
Tap MKUserTrackingModeButton to select MKUserTrackingModeFollowWithHeading
Issues:
This mode will not 'stick' and almost always exits after a matter of seconds (1-20).
The Blue 'Your Location' Annotation 'vibrates' and seems to move slightly from its central position whilst it's in MKUserTrackingModeFollowWithHeading.
Note that this is increasingly a problem as you zoom in. At the default magnification (which you are taken to when first tapping the MKUserTrackingModeButton Button, it is not so much of a problem.
An obvious workaround would be to limit zoom level, but unfortunately I need full zoom in my application.
I , too, got frustrated with this extremely annoying bug.
I have a deadline just around the corner, so I can't spend a lot of time trying to implement a workaround.
I had managed to get it to stay in MKUserTrackingModeFollowWithHeading at max zoom, but the User Location annotation "pin" still jittered around quite heavily, and in some edge cases, it was still canceling back into MKUserTrackingModeFollow.
What I did, initially, was to force a correction using BOOL flags in the regionDidChangeAnimated: delegate method, like so:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
NSLog(#"regionWillChangeAnimated:");
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
NSLog(#"regionDidChangeAnimated:");
[self forceCorrectUserTrackingMode];
}
- (void)forceCorrectUserTrackingMode {
if (shouldFollowWithHeading == YES && ([mapView userTrackingMode] != MKUserTrackingModeFollowWithHeading) ) {
NSLog(#"FORCE shouldFollowWithHeading! - setUserTrackingMode:MKUserTrackingModeFollowWithHeading");
[self.mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:YES];
} else if (shouldFollowWithHeading == NO && ([mapView userTrackingMode] != MKUserTrackingModeNone) ) {
NSLog(#"FORCE should NOT FollowWithHeading - setUserTrackingMode:MKUserTrackingModeNone");
[self.mapView setUserTrackingMode:MKUserTrackingModeNone animated:YES];
}
}
This actually got me pretty close, but it wasn't reliable enough, and like I said, I had to think about prioritizing other features for my deadline, so this is what I ended up doing:
First, I grabbed this code for a zoom category on MKMapKit: http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/
Next, I included this method that a visitor provided in that blog's comments:
- (int) getZoomLevel {
return 21 – round(log2(mapView.region.span.longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * mapView.bounds.size.width)));
}
Finally, a little trial and error testing the zoom levels vs. the occurrence of the bug led me to the following "workaround":
CLLocationCoordinate2D userLocation_CenterCoordinate = CLLocationCoordinate2DMake([locationManager location].coordinate.latitude, [locationManager location].coordinate.longitude);
int currentZoomLevel = [MKMapView getZoomLevelForMapView:mapView];
int newZoomLevel = 17;
if (currentZoomLevel > 17) {
NSLog(#"Adjusting mapView's zoomLevel from [%d] to [%d], also centering on user's location", currentZoomLevel, newZoomLevel);
[mapView setCenterCoordinate:userLocation_CenterCoordinate zoomLevel:newZoomLevel animated:NO];
} else {
NSLog(#"Centering on user's location, not adjusting zoom.");
[mapView setCenterCoordinate:userLocation_CenterCoordinate animated:NO];
}
Opened a TSI, and Apple confirmed that there is no workaround. I wonder if they'll have fixed it in 7 …

Resources