This is a small method of mine which takes the location manager's current location and focuses the map just a little bit above it to make room for some other subviews that I've added to the top of the map. If the span's lat/long deltas get too big (more than 1.0), every time the region is set, the span gets bigger and bigger until the map is zoomed out all the way, even without actually touching the map. I think it has something to do with reusing the map view's span, but I don't know exactly what's going on.
- (void)setRegion {
CLLocationCoordinate2D coord = locationManager.location.coordinate;
MKCoordinateSpan span = mapView.region.span;
coord.latitude += 0.002 * (span.latitudeDelta / 0.012523);
MKCoordinateRegion region = MKCoordinateRegionMake(coord, span);
[mapViewGlobal setRegion:region animated:animated];
}
From Apple's docs "If you want to change the center coordinate without changing the zoom level, use the setCenterCoordinate:animated: instead." MKMapView
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated
MKMapView will pick a new region that nicely fits the to a redefined zoom level while still displaying your entire target region and each time yo move north the span changes and things spiral out of control.
Also, your way of working out how much to change the latitude by is a bit odd. Aside from doing a multiple and divide when one would do the trick, it'll only work at a certain latitude (they get stretched away from the equator) and a certain zoom level. You'd be better off working out how many pixels you need the map scrolled by (presumably half the height of your subviews) and then using this function to work out where you need to center the map.
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view
Another way would be to put the subviews outside of the MKMapView, but that'll affect your aesthetics.
Related
I'm trying to achieve as follows:
User should always be at the center of the screen on MKMapView.
Route is drawn on the map as user will move.
I know, i can calculate the region to cover all the tracked points on the screen.
But here's my problem:
When i calculate the MKCoordinateRegion and setting it, it just fits the region that is best fitting to the screen but as soon as i'm trying to place user at center, a part of the line drawn on the MKMapView goes out of the screen.
Can anybody face this problem or any suggestions to handle this specific case, any help will be highly appreciated.
Thanks in advance.
I have accomplished it as follows:
Calculate the distance of farthest point from the user's current location (or any point you want to keep at the center).
Calculate the region, with your center point(user's current location in my case) and double the distance calculated above and make a region using te following code:
CLLocationCoordinate2D loc = [myLocation coordinate];
MKCoordinateRegion region =
MKCoordinateRegionMakeWithDistance(loc, distance * 2, distance * 2);
Set the region on the MapView and the trail will be shown inside the screen keeping user's location at the center.
Thanks.
When I try to place a pin in the center of the map using MKMapView's centerCoordinate it puts a pin roughly in the center, but it's several pixels south of the true center of the map.
I tried converting the map's center point to a coordinate
MKMapView.convertPoint(MKMapView.center) and that worked perfectly on ios8 but on ios7 is still off (now its south and west of the true center).
Anyone know how to determine how "off" the center coordinate is so I can adjust?
I need this because I am placing a crosshair image over the map and need the pin to appear in the center of the crosshair. I've verified with a ruler that the crosshair is centered on the map, it's the pin that is off.
In your answer you fixed one particular scenario where the center coordinate appears to be off, but really is not because it is just partially obscured by the status bar. Unfortunately, it is not as simple as that. There are other edge cases where the center coordinate actually can get offset a bit. (I notice it when I change frame of map view as keyboard is presented and later dismissed.) This is a curious little map view idiosyncrasy.
Anyone know how to determine how "off" the center coordinate is so I can adjust?
Yes, just convert the centerCoordinate to a CGPoint and compare to the center. The only trick is to make sure you do these in the same coordinate system (in the example below, the coordinate system of the map view):
func adjustOverlayCenterYConstraint() {
let mapCenter = mapView.convert(mapView.centerCoordinate, toPointTo: mapView)
let viewCenter = mapView.superview!.convert(mapView.center, to: mapView)
overlayCenterYConstraint.constant = mapCenter.y - viewCenter.y
}
In this example, I have a centerY constraint, whose constant I am adjusting, but it illustrates the idea of how to programmatically determine whether the center is offset a bit and how to adjust it. Theoretically, you might have to adjust the x coordinate, too, but the idea would be the same.
You said:
is still off (now its south and west of the true center)
If it is off both south and west, then the problem is likely just the coordinate system. Remember, center is in the coordinate system of the superview, so make sure to convert to a consistent coordinate system (either get coordinateCenter in coordinate system of map view’s superview and compare to center, or get both in the coordinate system of the mapview, like shown above).
Well I still don't know why in iOS7 MKMapView.convertPoint(MKMapView.center) differs from MKMapView.centerCoordinate, but did figure out why .centerCoordinate was off.
Part of the map was under the status bar and I ruled the center based on the visible part and overlaying images centered on the visible part, but the map computed center based on the whole map. So once I fixed the map not running under the status bar .centerCoordinate works and, on iOS7, works better than MKMapView.center.
I'm displaying several user's locations on a map simultaneously as circles of different colors.
I can do this using an annotation and then when the user's location updates use UIView:animateWithDuration: to move to their new location.
However there is a requirement that the size of the circles reflects the accuracy of the location i.e. very accurate equals a circle of size 10 meters, rough accuracy is represented as a circle of size 500 meters etc.
However there are two problems using annotations for this - the first is how to transform meters into a CGRect on the correct size to draw on the map. And the second is the annotations need to be resized if the user zooms the map.
So I was looking at using an overlay instead as that already has a radius and automatic resizing during zooming built in so it handles those two problems.
However it looks like overlays are meant to be static and their coordinate property is read only.
Is there some way I can make the overlays move as the user's location moves? (other than completely remove it and re-add it?)
[THis is for iOS 7 only]
I have to set my offline map that has been constructed with tilemill centralized on a custom point. Although i did not find a method like setRegion for MKMapView to make this job for me. Is there any way to set region to a rmmapview map?
no, regions like in ios are not available in route-map. you can set constraints, so that the user cant scroll out of your map:
// Constrain our map so the user can only browse through our exported map tiles
[self.mapView setConstraintsSW:CLLocationCoordinate2DMake(self.mapSrc.bottomRightOfCoverage.latitude, self.mapSrc.topLeftOfCoverage.longitude)
NE:CLLocationCoordinate2DMake(self.mapSrc.topLeftOfCoverage.latitude, self.mapSrc.bottomRightOfCoverage.longitude)];
and of course scrolling to specific position:
[self.mapView moveToLatLong:self.currentPosition.coordinate];
I solve my issue with the code below:
CLLocationCoordinate2D centerOfMap = CLLocationCoordinate2DMake(latitude, longitude);
[mapView setCenterCoordinate:centerOfMap];
With this way i have every time my map centralized to the point that i want.
Also,someone can adjust the zoom of the map and reach the result that he wants.
I have a MapView that takes up the full screen and a few elements toward the top of the screen that overlay the map. These top elements potentially cover the blue location marker.
The map is currently tracking fine with MKUserTrackingModeFollow, but I'd like to move the tracking focus down about an inch (obviously the metric will vary by zoom level) to ensure the marker isn't covered. Is there a way to do this with MKUserTrackingModeFollow?
I've considered moving the map with the top elements, but due to design constraints this isn't an option.
Instead of using the userTrackingMode of the MKMapView object to follow the user's location, you could set up a delegate of CLLocationManager to receive location tracking events, and with each location update event you receive, set the center coordinate of the map view, with your vertical offset added to the coordinate value.
You can use the various Map Kit functions and MKMapView methods to convert your offset from some fraction of the map view's bounds.height to a MKMapPoint or CLLocationDistance value.