13

I am new to iOS Programming and I have downloaded the google maps sdk for iOS and followed the instruction on their website ( as shown in this link https://developers.google.com/maps/documentation/ios/start ) and was able to get the map in my application.

Now I am trying to add a button on the screen at the bottom over Google maps for giving an option to the user to go back to the previous screen.

I just know that UIButton is a subclass of UIView and we can make a button appear on a view by making it the sub view of that class. Previously iOS used to use Google Maps by default by MKMapView and I have seen examples in books an on the Internet showing screen shots of apps where a button or a text box would appear on the map. But now just dragging the button in the interface builder doesn't help with the SDK of google maps.

Here is my code:

ViewController.h

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <GoogleMaps/GoogleMaps.h>


@interface ViewController : UIViewController 

@property (weak, nonatomic) IBOutlet UIButton *btn;


@end

ViewController.m

#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <GoogleMaps/GoogleMaps.h>
#import <CoreLocation/CoreLocation.h>


@interface ViewController ()

@end

@implementation ViewController
{
    GMSMapView *mapView_;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)loadView
{
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
    locationManager.distanceFilter = kCLDistanceFilterNone;

    locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
    [locationManager startUpdatingLocation];

    //Latitude and longitude of the current location of the device.
    double lati = locationManager.location.coordinate.latitude;
    double longi = locationManager.location.coordinate.longitude;
    NSLog(@"Latitude = %f", lati);
    NSLog(@"Longitude = %f", longi);

    CLLocation *myLocation = [[CLLocation alloc] initWithLatitude:lati longitude:longi];

    // Create a GMSCameraPosition that tells the map to display the coordinate

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:lati
                                                            longitude:longi
                                                                 zoom:11.5];

    mapView_ = [GMSMapView mapWithFrame:[[UIScreen mainScreen] bounds] camera:camera];
    mapView_.myLocationEnabled = YES;
    self.view = mapView_;

    // Creates a marker in the center of the map.
    GMSMarker *marker = [[GMSMarker alloc] init];
    marker.position = CLLocationCoordinate2DMake(lati, longi);
    marker.title = @"It's Me";
    marker.snippet = @"My Location";
    marker.map = mapView_;

    [mapView_ addSubview:_btn];
    [mapView_ bringSubviewToFront:_btn];

}
@end

You can see that in the last 2 lines I have made the button the subview of mapview and tried to bring it front. But this didn't help. Please let me know what is it that I am missing or if there is another way to do this by using some other function.

Please also do check the screenshot of the storyboard which I have created so that you can understand better what I am trying to do here.

Screenshot of the storyboard

Thanks.

Manas
  • 1,313
  • 3
  • 12
  • 16
  • 1
    Whats the point of posting this as new question where it has already been asked [here](http://stackoverflow.com/q/16436352/593709) – Adil Soomro May 20 '13 at 06:48

5 Answers5

15

GMSMapView is subclass of UIView so you can add subviews as to any other view

Try this code

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(mapView_.bounds.size.width - 110, mapView_.bounds.size.height - 30, 100, 20);
button.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
[button setTitle:@"Button" forState:UIControlStateNormal];
[mapView_ addSubview:button];

It adds 100x20 button as the subview of the GMSMapView, positioned to the bottom right corner. I have tested it and the button can be touched as in any other view

Edit: Also move all your code from -loadView to -viewDidLoad. -loadView method is never called when using IB to create UI. Docs to -loadView says:

If you use Interface Builder to create your views and initialize the view controller, you must not override this method.

Edit 2: I believe when you create view hierarchy using Interface Builder, you CAN NOT reset self.view property like you are doing.

Do this in your -viewDidLoad

[self.view addSubview: mapView_];

instead of

self.view = mapView_;

if you are passing GMSMapView to the self.view property, the map is only view which is in the controller from this point. Thats, I believe, the reason why u can't see your IB-created button.

Lukas Kukacka
  • 7,604
  • 2
  • 25
  • 50
  • Thanks it worked. But I will be very thankful to you if you could just tell me where I was going wrong. Can't I make a UIButton through interface builder the way you did it programatically? – Manas May 20 '13 at 08:05
  • I had to make a change in the last line to make it work I changed `[_mapView addSubview:button];` to `[mapView_ addSubview:button];` – Manas May 20 '13 at 08:20
  • Im sorry but I can't help you, because but Im not working with Interface builder UI anymore. Maybe you could try to move code from `-loadView` to `-viewDidLoad`. – Lukas Kukacka May 20 '13 at 08:22
  • Sorry, I have fixed the code above according to your comment. – Lukas Kukacka May 20 '13 at 08:24
  • Another problem that I am facing now is that if I can't set a button on my storyboard then how to set the identifier for a segue to go to the previous view? – Manas May 20 '13 at 08:41
  • @LukasKukacka: The solution you gave me is fine to create a button programatically which makes a button appear on the map but that doesn't help me go back to the previous screen as I can't create a segue at runtime. It should be present in the storyboard and the button which I created in the storyboard doesn't appear on the view. Please again check the last two lines of ViewController.m And following your suggestion I also moved the code to `-viewDidLoad` from `-loadView` – MK Singh May 20 '13 at 10:41
  • @LukasKukacka: I believe what you mentioned in your second edit must be theoretically correct but when I replaced `self.view = mapView_;` with `[self.view addSubview: mapView_];` my program went into some infinite loop and the screen didn't change from the slider view to map view and I had put an NSLog command in the function which got printed continuously for 5 minutes. Finally I had to switch back to my previous code. – Manas May 20 '13 at 13:09
  • I thought that maybe putting the code to `-loadView` instead of `-viewDidLoad` may stop my program from going into an infinite loop, but it didn't. – Manas May 20 '13 at 13:14
  • I am now thinking that displaying the map through Navigation controller could be a easier. But the only disadvantage is that the Navigation bar would eat up some space of the screen even though I am interested in only a small button to the needful. – Manas May 20 '13 at 13:30
  • I was able to get an alternate solution to my problem as mentioned in the comment above by me by embedding a navigation controller. – Manas Oct 22 '13 at 11:02
  • I am using swift and the Edit 2 doesn't seem to work. I moved my code to viewDidLoad() and I do see my buttons but the view.addSubview(mapView) doesn't work. I tried view.insertSubview at index 0 as well and it has exact same effect. Any ideas what im doing wrong? – Xitcod13 Nov 20 '16 at 00:09
3

Make your view normally with InterfaceBuilder and to put mapView at 0 index subview :

mapView_ = [GMSMapView mapWithFrame:self.view.bounds camera:camera];
mapView_.myLocationEnabled = YES;
[self.view insertSubview:mapView_ atIndex:0];

Thanks to Raul Clauss from this thread

And you can custom the size of mapView, change :

mapView_ = [GMSMapView mapWithFrame:_mapHolder.bounds camera:camera];
mapView_.myLocationEnabled = YES;
[_mapHolder insertSubview:mapView_ atIndex:0];

Where mapHolder, is a UIView made inside the IB.

Community
  • 1
  • 1
Felipe FMMobile
  • 1,641
  • 20
  • 17
3

I faced the same issue and the fix is very easy, just override this UIViewController method:
-(void) viewWillAppear:(BOOL)animated and put your UIButton creation logic inside that method.

Example:

-(void) viewWillAppear:(BOOL)animated
{
 locationButton = [UIButton buttonWithType:UIButtonTypeCustom];
 locationButton.frame = CGRectMake(0, 30, self.view.frame.size.width/6, self.view.frame.size.height/6);
 [locationButton setImage:[UIImage imageNamed:@"location_enabled.png"] forState:UIControlStateNormal];
 [self.view addSubview:locationButton];
}
Mihir Oza
  • 2,768
  • 3
  • 35
  • 61
DevSherif
  • 147
  • 2
  • 11
2

This problem occur because you try to add the map view with the code, earlier you add the button with the help of interface builder. When you add the mapView it would add at the top of the view that's why your button is not shown.

You have two options for doing this.

First approach

  • Drag and drop the UIButton from the interface builder and set the constraints accordingly enter image description here

  • Then create the outlet of that button in the corresponding viewController

    @IBOutlet weak var bottonToAdd: UIButton!

  • After adding the map view to the view paste the blow code to bring the button at the top mapViewForScreen.addSubview(self.bottonToAdd) mapViewForScreen.bringSubviewToFront(self.bottonToAdd)

After the above three step you can find out that you hav the button over mapview

enter image description here

Second approach

If you don't want to use the interface builder you can use the below code for the same.

    var bottonToAdd:UIButton = UIButton()
    bottonToAdd.setTitle("Button To Add", for: .normal)
    bottonToAdd.sizeToFit()
    bottonToAdd.center = mapViewForScreen.center
    bottonToAdd.tintColor = UIColor.blue
    mapViewForScreen.addSubview(bottonToAdd)
    mapViewForScreen.bringSubviewToFront(bottonToAdd)
shubham
  • 611
  • 7
  • 16
0
 let mapButton:UIButton = UIButton(frame: CGRect(x:self.view.bounds.width-50, y: 20, width: 40, height: 40)) //Swfit 5
    mapButton.backgroundColor = UIColor.clear
    mapButton.setImage(UIImage(named: "list"), for: UIControl.State.normal)
    mapButton.setImage(UIImage(named: "map"), for: UIControl.State.selected)
    mapButton.addTarget(self, action:#selector(self.mapListClicked), for: .touchUpInside)
    self.view.addSubview(mapButton)