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.
Related
I have a mapview in xcode, which is all working well.
What my page does just now is like this:
downloads a bunch of data and locations from a backend database
populates a mapview with locations and drops pins
populates a table underneath the mapview
That all works great, and I end up with a mapview with a load of pins, and a tableview that has the details of those pins.
What I want to do now, is allow the user to tap on a row from the tableview, and have the map zoom and centre to the corresponding map pin, and then automatically activate the annotation pin callout.
In my 'didselectrow' method, I have the following:
MKCoordinateSpan span = MKCoordinateSpanMake(0.1f, 0.1f);
CLLocationCoordinate2D coordinate = { [item.latitude floatValue], [item.longitude floatValue] };
MKCoordinateRegion region = { coordinate, span };
[self.mapView setRegion:region animated:YES];
This works great too. Tapping on the table row will zoom to and centre the map pin at this location.
I just can't get the last step of firing the annotation pin callout to work.
I have tried:
[mapview annotationsInMapRect:mapview.visibleMapRect];
But this isn't working, and it is possible that there still might be 2 or 3 map pins in the visible area.
What I need to do is to get the pin nearest to the centred location (see above - item.latitude / item.longitude) to automatically open it's callout.
Everything in the code is set up and working, and the map pins have callouts that fire when tapped on, I just need this last stage of having the pin nearest the centre location to open automatically.
Can anyone help with this?
I have tried various other suggestions on SO, but none seem to fit this requirement.
I think I have got solution for your problem you need to use this [_mapView setSelectedAnnotations:#[[[self.mapView annotations] lastObject]]];
For testing I have created an small project that have these 2 methods.
- (IBAction)buttonTouched:(id)sender {
[_mapView showAnnotations:[self.mapView annotations] animated:YES];
[self performSelector:#selector(showAnnotationCallOut) withObject:nil afterDelay:1.0f];
}
- (void) showAnnotationCallOut {
[_mapView setSelectedAnnotations:#[[[self.mapView annotations] lastObject]]];
}
Note: I have called just one annotation for test that why I am calling last object. You'll need to call it for specific annotation of your annotation array.
Edit: According to Richerd's comment here is solution for problem of finding the annotion and showing the callout fro that.
for (MapViewAnnotation *annotion in [self.mapView annotion]) {
if ([annotion.identifire isEqualToString:annotationToCallCallOutIdentifier]) {
//[_mapView setSelectedAnnotations:#[annotation]];
[_mapView selectAnnotation:annotation animated:YES];
break;//don't break if there are can be more than one callouts
}
}
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
I am using a MKUserTrackingBarButtonItem button to allow the user to automatically track their location on a map. The problem is that when they tap this button, it is zoomed too far out. I want it to start at a specified zoom level (i.e. span). How can I achieve this?
When the user taps the button to change to MKUserTrackingModeFollow, it seems to use the same zoom level that the user last manually changed to (i.e. using gestures on the map). Attempting to specify a different zoom level via setRegion or setVisibleMapRect does not affect what zoom level will be used when the mode is changed to MKUserTrackingModeFollow.
Attempting to override mapView:didChangeUserTrackingMode: to set the region causes the mode to be changed back to MKUserTrackingModeNone. Example:
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mode == MKUserTrackingModeFollow) {
CLLocationCoordinate2D center = mapView.userLocation.location.coordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002306, 0.001717);
[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
// [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
}
}
If I attempt to reset the mode immediately after setting the region, it works fine if the user is stationary, but zooms back out if the user is moving.
The simplest solution would be if there was a way to simply specify something like a zoom level for MKUserTraking by sending it my span value. However, since that doesn't seem to exist, what else can I do?
I had the same issue and used a different approach to fix it. You can use the MapCamera function for this instead of that button.
On each new location do this:
MKMapCamera *newCamera = [MKMapCamera cameraLookingAtCenterCoordinate:[newLocation coordinate]
fromEyeCoordinate:[oldLocation coordinate]
eyeAltitude:2000];
[mapView setCamera:newCamera animated:TRUE];
And play with the eyeAltitude.
If the user manually zooms in or out you can read the altitude value from mapview.camera.altitude also don't update the camera when the user is manually using the map.
According to apple documentation used here
https://developer.apple.com/reference/mapkit/mkmapview/1616208-usertrackingmode
Setting the tracking mode to follow or followWithHeading causes the map view to center the map on that location and begin tracking the user’s location. If the map is zoomed out, the map view automatically zooms in on the user’s location, effectively changing the current visible region.
Here changing the region does not effect your visible region due to that reason.
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mode == MKUserTrackingModeFollow) {
CLLocationCoordinate2D center = mapView.userLocation.location.coordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002306, 0.001717);
[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
// [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:NO];
}
}
So you just need to change center coordinate on didChangeUserTrackingMode instead of changing the whole region
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
if (mode == MKUserTrackingModeFollow) {
[self.mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
}
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
[self.mapView setCenterCoordinate:mapViewuserLocation.location.coordinate animated:YES];
}
on click of MKUserTrackingBarButtonItem change the zoom level
CLLocationCoordinate2D center = mapView.userLocation.location.coordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002306, 0.001717);
[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
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.
I use the following code to get my location when a user presses a button
[mapview setShowsUserLocation:YES];
and then the follwoing to center the map to te user's location
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
[mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
}
My question is how to prevent the map from always centering on my location? I want to allow the user to pan the map.
Center on the location only the first time you show the map. Here is some pseudo code...
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if(shouldCenterLocation){
[mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
shouldCenterLocation = FALSE;
}
//do all your other stuff here
}
shouldCenterLocation is a boolean flag that you can set to TRUE the first time the map is shown, then set it to FALSE until you exit the view (or any other condition you have for showing the center location).
edit: you can toggle the state of shouldCenterLocation in the same method that you handle the button press.
I think it came in with iOS5, you can now drop the delegate stuff and just set the userTrackingMode of the MKMapView. Set it to MKUserTrackingModeFollow to make the make move along with the user and then when they start panning the map around it'll turn off the tracking mode automatically, you then just need to provide a button to turn it back on.
On swift 3 I prefer use animated method:
mapView.setUserTrackingMode(.follow, animated: true)
but set property good worked:
mapView.userTrackingMode = .follow