In my application I am using Google Maps SDK.
I have a full screen map in my application.
The problem is that Google logo is cut off from bottom part of the screen behind navigation tab.
I don't know what to change anymore to resize map to show logo on a screen.
I would attach screenshot of the problem but I don't have enough reputation.
As I am fairly new with Obj-C and programming in Xcode, I may have forgotten to post some part of code essential for maps implementation.
- (void)viewDidLoad
{
[super viewDidLoad];
_firstLocationUpdate = NO;
_errorView.layer.cornerRadius = 5;
_errorView.clipsToBounds = YES;
GMSCameraPosition *camera = [GMSCameraPosition cameraWithTarget:_mapView.myLocation.coordinate zoom:14];
_mapView = [GMSMapView mapWithFrame:self.view.frame camera:camera];
_mapView.delegate = self;
[self.view addSubview:_mapView];
[self.view sendSubviewToBack:_mapView];
}
I managed to force it a little bit up, but this is really ugly way of doing it.
_mapView = [GMSMapView
mapWithFrame: CGRectMake(
0, -50,
self.view.frame.size.width, self.view.frame.size.height)
camera: camera];
[self.view addSubview:_mapView];
[self.view sendSubviewToBack:_mapView];
Another option would be to pad the controls while leaving the view the same size:
// top, left, bottom, right
_mapView.padding = UIEdgeInsetsMake(0.0, 0.0, 50.0, 0.0);
Testing with SDK 1.8, it moves the Google logo and the various controls.
Google SDK documentation for the padding property:
Controls the 'visible' region of the view.
By applying padding an area arround the edge of the view can be created which will contain map data but will not contain UI controls.
If the padding is not balanced, the visual center of the view will move as appropriate. Padding will also affect the projection property so the visible region will not include the padding area. GMSCameraUpdate fitToBounds will ensure that both this padding and any padding requested will be taken into account.
This property may be animated within a UIView-based animation block.
You are pretty close, you just need to set the size of the map frame to not include the space behind the tab view. So something like this:
_mapView = [GMSMapView
mapWithFrame: CGRectMake(
0,
0,
self.view.frame.size.width,
self.view.frame.size.height - {the height of the tab view})
camera: camera];
Related
I am trying to load a Google Map into my application within a subview. When I initialize my GMSMapView in iOS, the current location is in the top left corner of the map instead of the center screen. This is true if I were to press the "My location" button as well.
This seems to be an issue when running on my phones but not on simulators. How do I get it so that it is set up correctly in the center?
I've tried rearranging code and loading the map differently. I think it might be due to Autolayout Constraints, as when I set mapView.translatesAutoresizingMaskIntoConstraints = true; then the location is in the center, but my view is messed up.
I currently have GMSMapView set up as the custom class of my view with auto layout constraints set up to resize it.
I load up my GPS class and set the frame with this.
gpsVC = [[GPSViewController alloc] init];
gpsVC.view.frame=CGRectMake(0, CGRectGetMaxY(self.segmentTopView.frame), CGRectGetWidth(self.mainView.frame), CGRectGetHeight(self.mainView.frame)-CGRectGetHeight(self.topView.frame)-CGRectGetMaxY(self.segmentTopView.frame));
[self.segmentView addSubview:gpsVC.view];
And in my GPSViewController I set up the map camera as follows:
self.mapView.myLocationEnabled = YES;
GMSCameraPosition *camera=[GMSCameraPosition cameraWithLatitude:myLocation.coordinate.latitude longitude:myLocation.coordinate.longitude zoom:[mapDefaultZoomLevel floatValue]];
self.mapView.camera=camera;
Is anyone else experiencing this, and did you find any solution to this problem?
Edit: Here are some images (Links because I can't put in images yet)
https://imgur.com/FEMfwri
https://imgur.com/ySQio5b
https://imgur.com/9kijxbT
for anyone wondering I eventually found a workaround solution to the problem I was having.
I believe that there was a view frame issue with auto-layout that was happening when my GPSViewController initialized. I avoided this issue by setting up my Google Map after my view has been setup. I removed the GMSMapView from the custom class of my UIView and instead programmatically created the map manually and added it to the view.
In my MasterViewController.m:
gpsVC = [[GPSViewController alloc] init];
gpsVC.view.frame=CGRectMake(0, CGRectGetMaxY(self.segmentTopView.frame), CGRectGetWidth(self.segmentView.frame), CGRectGetHeight(self.segmentView.frame)-CGRectGetHeight(self.segmentTopView.frame));
[gpsVC setupMap];
In my GPSViewController.m (abridged):
-(void)setupMap{
GMSCameraPosition *camera=[GMSCameraPosition cameraWithLatitude:coordinate.latitude longitude:coordinate.longitude zoom:mapDefaultZoomLevel];
self.mapView = [GMSMapView mapWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)) camera:camera];
self.mapView.myLocationEnabled = YES;
self.mapView.settings.myLocationButton = YES;
self.mapView.settings.compassButton = YES;
self.mapView.delegate=self;
[self.myView addSubview:self.mapView];
}
Looks like you are doing it correctly, the only thing I can't say for sure is whether you are centering your map correctly in the sub view. But here are some other map tricks you can try, if the problem is with the map:
[self.mapView clear];
// Set map view and display
double zoom = 14;
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:[myLocation.latitude doubleValue]
longitude:[myLocation.longitude doubleValue]
zoom:zoom];
// Initialize Map View
self.mapView.camera = camera;
self.mapView.myLocationEnabled = YES;
__block GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];
//You can try setting a couple of points east and west of your current location and including them in the bounds
CLLocation westLocation = myLocation;
westLocation.longitude += .005;
CLLocation eastLocation = myLocation;
eastLocation.longitude -= .005;
bounds = [bounds includingCoordinate:myLocation.position];
bounds = [bounds includingCoordinate:eastLocation.position];
bounds = [bounds includingCoordinate:westLocation.position];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self.mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:40.0f]];
} else {
[self.mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:100.0f]];
}
Same issue with you. I was delay init google mapview to test. And It works normally again.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self initGoogleMap];
});
I want to change iOS Google Map SDK zoom level using with GMSCameraUpdate:fitBounds:withEdgeInsets. But the problem is the Google map is taking the default zoom level when i use GMSCameraUpdate:fitBounds:withEdgeInsets. Here am using withEdgeInsets to change map position. Any help will be appreciated.
Below is my complete code.
GMSCoordinateBounds *markerBounds = [[GMSCoordinateBounds alloc] initWithPath:gmsPath];
GMSCameraUpdate *updatedCamera = [GMSCameraUpdate fitBounds:markerBounds withEdgeInsets:UIEdgeInsetsMake(-500, 0, 0, 0)];
[mapView_ animateWithCameraUpdate:updatedCamera];
Here gmsPath contains multiple coordinates for [GMSMutablePath path].
When i use [mapView_ animateToZoom:10]; then withEdgeInsets is not working.
I searched google and stackoverflow but i could not find correct result.
You should probably resize the map to fit in the available space, rather than use an edge inset to have the same effect. In particular, resizing the map would make sure that the Google logo is visible, which is a requirement of using the SDK.
If you don't want to do that, then I think you should use something like UIEdgeInsetsMake(0, 0, 500, 0), ie a positive inset on the bottom edge, not a negative inset on the top edge. Instead of hard-coding 500, you should use the height of your table (in points).
I found the solution with UIEdgeInsetsMake. The following is the solution.
GMSCoordinateBounds *markerBounds = [[GMSCoordinateBounds alloc] initWithPath:gmsPath];
GMSCameraUpdate *updatedCamera = [GMSCameraUpdate fitBounds:markerBounds withEdgeInsets:UIEdgeInsetsMake(44, 0, self.view.frame.size.height - 180, 0)];
[mapView_ animateWithCameraUpdate:updatedCamera];
-180 is the available space above UITableView
I am trying to animate the movement of a GMSmarker (or any object for that sake), between 2 points.
(Just to clarify this is using either Apple Maps or Google Maps)
So I would have the initalPoint, and the newPoint, and it would animate the icon that is marking 'position' from intialPoint to newPoint.
I have rigorously searched the Google Maps SDK myself but couldn't find anything that would do it.
Can anyone provide and code samples/tutorials on how to do such a thing?
You could overlay your own custom "marker" and animate it using UIView animations. For example, the following code would move a red square from pointA to pointB.
- (void)moveMarker
{
CGPoint pointA = CGPointMake(30, 40);
CGPoint pointB = CGPointMake(120,65);
UIView *marker = [[UIView alloc] initWithFrame:
CGRectMake(pointA.x, pointA.y, 10, 10)];
marker.backgroundColor = [UIColor redColor];
[mapViewIWantToAddAMarkerTo addSubview:marker];
[UIView animateWithDuration:5 animations:^{
marker.frame = CGRectMake(pointB.x, pointB.y, 10, 10);
}];
}
I now have this working. The way to do this is to simple update the location of a MKPointAnnotation (using apple maps)
In swift it goes:
var thePoint : MKPointAnnotation()
thePoint.setCoordinates([CLLocationCoordainte2D variable goes here])
Do this multiple times a second and it appears to smoothly move.
I am making a driving game for the iOS, where a car (UIView) is put on top of the google maps ios api. I am having trouble detecting collisions with the car and the grey buildings that appear on the map.
I have been trying to do it by pixel color i.e. checking if the pixel color, just ahead of the car, is the color of a buildings roof (grey). There is no direct access to an iPhones pixel color, so I am using the google maps screenshot method to get an image and get the pixel color from that. The problem is, is that I can only take a screen shot of the screen I just left. I am using
mapImage = [GMSScreenshot screenshotOfMainScreen];. I have also tried getting the window and screen and calling mapImage = [GMSScreenshot screenshotOfScreen:topWindow.screen]; Both have the same effect.
What is a solution to this problem? Can you think of a better way of handling collisions for this situation? Does reverse geocoding have the ability to detect the tops of buildings vs streets?
Thanks for any and all help!
EDIT:
Images:
Interface Builder: Left is the main menu, right is the game. The Ui image view in the upper left corner is set as the current screen shot image for referencing purposes. This how I knew It was off
Game Play, As you can see, it is only presenting the previous menu.
My viewdidLoad function: Not much other than this thats related to getting the image.
- (void)viewDidLoad
{
[super viewDidLoad];
cameraPosition = CLLocationCoordinate2DMake(42.271291, -83.729918);
moveDistance = .00055;
cA = [UIColor colorWithRed:.937255 green:.921569 blue:.886275 alpha:1];
camera = [GMSCameraPosition cameraWithLatitude:cameraPosition.latitude
longitude:cameraPosition.longitude
zoom:19
bearing:0
viewingAngle:0];
mapView_ = [GMSMapView mapWithFrame:CGRectMake(0, 0, 480, 300) camera:camera];
mapView_.myLocationEnabled = NO;
[self.view addSubview:mapView_];
car_ = [[Car alloc] initWithFrame:CGRectMake(240, 150, 13, 29) withImage:[UIImage imageNamed:#"carA-01.png"]];
[self.view addSubview:car_];
[self.view addSubview:controllerView];
updateClock = [NSTimer scheduledTimerWithTimeInterval:(1/20)
target:self
selector:#selector(update)
userInfo:nil
repeats:YES];
crashClock = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(checkCrash)
userInfo:nil
repeats:YES];
UIWindow *topWindow = [[UIApplication sharedApplication].windows objectAtIndex:0];
mapImage = [GMSScreenshot screenshotOfScreen:topWindow.screen];
// mapImage = [GMSScreenshot screenshotOfMainScreen];
}
Are you getting a new screenshot every frame (or on some interval), eg from your update callback?
The GMSMapView doesn't render immediately when you create or make changes to it - it renders later on its next update. Therefore when you take the screenshot in viewDidLoad you're probably getting what was on the screen at the time that the map view was added, ie the initial menu.
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.