I want to show my current location lower in the map (iOS 6 and iOS 7) as per below screen shot to user can see further view [google default app with google map].
Right now, the cursor that shows center in the view as per below image [my app with apple map] .
Therefore the largest part of the screen is used to display what's behind, while it cannot look forward very far.
In the first image and second image, I compare to Google Navigation, which shows the current position much lower in the screen, for about the same rotation angle. I've added some arrows to show what I'm talking about.
i tried below code for set center because i cannot find to set lower.
mapView.userTrackingMode = MKUserTrackingModeFollow;
and also try below method
[mapView setCenterCoordinate:currentLocation.coordinate animated:YES];
Setting layoutMargins on MKMapView works just fine.
According to docs,
The default spacing to use when laying out content in the view.
In iOS 11 and later, use the directionalLayoutMargins property to
specify layout margins instead of this property.
To offset camera's centering point to be centered in bottom half of the MKMapView, just set UIEdgeInsets.top to half of MKMapView's height.
class MapViewController: UIViewController {
#IBOutlet var mapView: MKMapView!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let layoutMargins = UIEdgeInsets(top: self.mapView.bounds.size.height / 2, left: 0, bottom: 0, right: 0)
self.mapView.layoutMargins = layoutMargins
}
Don't set the userTrackingMode or the map's centerCoordinate.
Instead, you can try pointing the MKMapCamera to a coordinate slightly ahead of the user's in the direction they are heading. This will automatically put the user's location lower on the screen.
Calculating the coordinate "a short distance ahead" is not currently built into the iOS SDK so you'd have to calculate it manually.
One way to do it is using the method shown in:
Calculate new coordinate x meters and y degree away from one coordinate.
Using the coordinateFromCoord:atDistanceKm:atBearingDegrees: method from that answer, you could set the camera like this:
MKMapCamera *cam = [MKMapCamera camera];
CLLocationCoordinate2D coordinateAhead =
[self coordinateFromCoord:currentLocation.coordinate
atDistanceKm:0.15
atBearingDegrees:currentLocation.course];
//adjust distance (0.15 km) as needed
cam.centerCoordinate = coordinateAhead;
cam.heading = currentLocation.course;
cam.pitch = 80; //adjust pitch as needed (0=look straight down)
cam.altitude = 100; //adjust as needed (meters)
[mapView setCamera:cam animated:YES];
Try this with the "City Bicycle Ride", "City Run", or "Freeway Drive" in the simulator.
You may need to adjust some of the numbers to get the perspective you want.
A simple workaround that should work is to make the MKMapView frame bigger than the screen of the device.
Something like:
MapViewHeight = (WindowHeight - desiredOffsetFromBottom)*2
Related
I've got an mkmapview which has annotations on it. I want to resize the mapview (by changing it's height constraint's constant from 200 to 400), but I don't want the map's center coordinate to move at all.
Currently, when the map is resized, the center coordinate moves so that it stays in the center of the map (from (x, 100) to (x, 200) if the map height goes from 200 to 400).
It seems the only solution to this is executing code like this:
var coordinate = self.mapView.centerCoordinate
coordinate.latitude += self.mapView.region.span.latitudeDelta * 0.25;
self.mapView.setCenterCoordinate(coordinate, animated: true)
This does work, but the issue I'm encountering is mainly with animation. I want to update the constraint in an animated fashion as well:
mapHeightConstraint.constant = 400
UIView.animateWithDuration(0.35) {
self.view.layoutIfNeeded()
}
This results in the map not being animated regardless of whether I animate the constraint before or after I adjust the center.
I'd like both animations to occur simultaneously and take the same amount of time or find another solution.
I have this view with a map that covers most of the screen's area.
On top of the map, I have some images, buttons, text boxes. They're located in the top portion of the map, which I'm calling here "useless map", while the bottom part is for actually viewing the map. This is the "useful map".
By default, the map property centerCoordinate is the center with respect to the full map, as seen as the red circle in the image:
The useful map is marked in green, and I wanted the green circle to be used as a center point.
I can center the map or add a pin, for instance, in that precise point by adding or subtracting from the coordinate's latitude, but the actual value I need to add depends on the zoom level.
Is it possible to change the map center point, or make any changes that can make the map act as if that point (the green circle) is the center?
The purpose of this is that I want to drop a pin at (or move the current pin to) the pseudo-center point (the green one) every time the user drags the map. So to do this, I'd need to get the centerCoordinate (the red one) and then add an offset.
You can add layout margins for the map.
extension MKMapView {
/*
* This is to hide the legal link on the map.
*/
public func centerMapWithBottom(bottomPadding: CGFloat) {
self.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: bottomPadding, right: 0)
}
}
This will shift the map center up. Similarly, it can be done for other scenarios as well.
Instead of showing user location for the map just drop an annotation pin at
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = myCoordinate; //CLLocationCoordinate2D myCoordinate
[self.mapView addAnnotation:point];
I have a few annotations added to a MKMapView, and when the user clicks on one of the annotations, it displays a UICalloutView with a right accessory button which adds a UIView to the map, displaying some information about that specific location. This UIView is centred in the superview of the map, and in order to show that the information in that view is relative to the annotation, I would like to shift the visible map rect down (on the y axis), and center it on the x axis so that the annotation is directly under the view.
I am doing the following to centre the annotation, however, I don't know how to move the annotation down on the y axis so that it sits under the added UIView. Please can you tell me how I can do so?
[self.mapView setCenterCoordinate:[annotation coordinate] animated:YES];
If you want to shift the map down so it's centered on a particular coordinate, but shift it down, say, 40%, so you have space for something above it, you could do something like the following:
CLLocationCoordinate2D center = coordinate;
center.latitude -= self.mapView.region.span.latitudeDelta * 0.40;
[self.mapView setCenterCoordinate:center animated:YES];
You can get the size of the information view, then you know how much you want to use the map (based on the difference between its size and the map view size). Now you know the offset, you can calculate the point (in the view coordinate system) that should be moved to the centre so that the annotation is moved down). Then you can use convertPoint:toCoordinateFromView: to find the coordinate for that point to use with setCenterCoordinate:animated:.
I really love the way foursquare designed venue detail view. Especially the map with venue location in the "header" of view ... How was it done? Details are obviously some uiscrollview (maybe uitableview?) and behind it (in the header) there is a map so when you scroll up the map is beeing uncovered as the scroll view bounces... does anyone has an idea how to do this?
Here's the way I manage to reproduce it:-
You need a UIViewController with a UIScrollView as its view. Then, the content of the UIView you add to your scrollview should look like this :-
- The frame of the MKMapView have a negative y position. In this case, we can only see 100pts of the maps in the default state (before dragging).
- You need to disable zooming and scrolling on your MKMapView instance.
Then, the trick is to move down the centerCoordinate of the MKMapView when you drag down, and adjust its center position.
For that, we compute how much 1point represent as a delta latitude so that we know how much the center coordinate of the map should be moved when being dragged of x points on the screen :-
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView* scrollView = (UIScrollView*)self.view;
[scrollView addSubview:contentView];
scrollView.contentSize = contentView.frame.size;
scrollView.delegate = self;
center = CLLocationCoordinate2DMake(43.6010, 7.0774);
mapView.region = MKCoordinateRegionMakeWithDistance(center, 1000, 1000);
mapView.centerCoordinate = center;
//We compute how much latitude represent 1point.
//so that we know how much the center coordinate of the map should be moved
//when being dragged.
CLLocationCoordinate2D referencePosition = [mapView convertPoint:CGPointMake(0, 0) toCoordinateFromView:mapView];
CLLocationCoordinate2D referencePosition2 = [mapView convertPoint:CGPointMake(0, 100) toCoordinateFromView:mapView];
deltaLatFor1px = (referencePosition2.latitude - referencePosition.latitude)/100;
}
Once those properties are initialized, we need to implement the behavior of the UIScrollViewDelegate. When we drag, we convert the move expressed in points to a latitude. And then, we move the center of the map using the half of this value.
- (void)scrollViewDidScroll:(UIScrollView *)theScrollView {
CGFloat y = theScrollView.contentOffset.y;
// did we drag ?
if (y<0) {
//we moved y pixels down, how much latitude is that ?
double deltaLat = y*deltaLatFor1px;
//Move the center coordinate accordingly
CLLocationCoordinate2D newCenter = CLLocationCoordinate2DMake(center.latitude-deltaLat/2, center.longitude);
mapView.centerCoordinate = newCenter;
}
}
You get the same behavior as the foursquare app (but better: in the foursquare app, the maps recenter tends to jump, here, changing the center is done smoothly).
The example above is nice. If you need more help, I think they're using something very similar to RBParallaxTableViewController. https://github.com/Rheeseyb/RBParallaxTableViewController
It's essentially the same effect that Path uses for its header photo.
Yonel's answer is nice, but I found a problem as I have a pin at the center of the map. Because the negative Y, the point is hidden under my UINavigationBar.
Then, I didn't set the Negative Y, and I correct my mapView.frame according the scroll offset.
My mapView is 320 x 160
_mapView.frame = CGRectMake(0, 160, 320, -160+y);
Hope this helps someone.
I'm trying to setup an offline map in an iPhone app, but the result is not very good.
I'm using the route-me framework, I've got an offline file .db (created by tiles2sqlite) and the map view is constrained with coordinates (using setConstraintsSW:NE:).
My problem is appearing when zooming out (pinch gesture), this error message "Zooming will move map out of bounds: no zoom" is always present and it's very difficult to zoom out when you are not near the real center of the map.
Is there a solution to have the same result as in Offmaps (iOS app) where the map has a nice scrollview behavior?
Cheers.
Cyril
I had to edit RMMapView.m source code to make a quick fix. Find - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center animated:(BOOL)animated method (near line 300). It has constrain logic, I turned it off:
- (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center animated:(BOOL)animated
{
if ( _constrainMovement && false ) // turn constraint checks off
{
//check that bounds after zoom don't exceed map constraints
//the logic is copued from the method zoomByFactor,
float _zoomFactor = [self.contents adjustZoomForBoundingMask:zoomFactor];
float zoomDelta = log2f(_zoomFactor);
...
}
...
}
Now map is zoomed smoothly, but this fix could have side effects.
Instead you can use of setting setConstraintsSW:NE: we can set RMMapview as,
RMDBMapSource *mapSrc = [[[RMDBMapSource alloc] initWithPath:#"mapDB.sqlite"] autorelease];
[[RMMapContents alloc] initWithView:mapView tilesource:mapSrc centerLatLon:mapSrc.centerOfCoverage zoomLevel:17 maxZoomLevel:18 minZoomLevel:15 backgroundImage:image screenScale:10 ];
This will enable your zooming acording to your set parameter