Search code examples
iosswiftuibuttontouch-eventgoogle-maps-sdk-ios

Can't receive touch events from UIButtons placed ontop of GMSMapView


I'm trying to place some static UI such as buttons on top of google maps.

Currently for the screen I have

UIView
   - GMSMapView
   - UIView
      - UIButton

I changed the second UIView's layer.zPosition so that the view and button would show up, but I can't receive any touch events (touchupinside) from the UIButton.


Solution

  • You shouldn't have to change the UIView.zPosition given your set up. I would take a second look at the point in your code when you add the second UIView, since the ordering that you call each view will matter if the GMSMapView and UIView are going to be at the same subview level.

    Meaning, the UIView can be potentially be obstructed by some layer of the GMSMapView. (Take note, that the GMSMapView is made of several layers, and it's very possible that the GMSUISettings layer is intercepting the touch events for the button)

    I made a very simple test app using google's sample code (see here) plus the code for a UIView and UIButton:

    - (void)viewDidLoad {
         [super viewDidLoad];
    
         // Exact google code
         GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86
                                                            longitude:151.20
                                                                 zoom:6];
         mapView_ = [GMSMapView mapWithFrame:CGRectZero 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(-33.86, 151.20);
         marker.title = @"Sydney";
         marker.snippet = @"Australia";
         marker.map = mapView_;
    
        // UIView code
        UIView * buttonView = [[UIView alloc] initWithFrame:CGRectMake(25, 25, 150, 100)];
        [buttonView setBackgroundColor:[UIColor redColor]];
        [mapView_ addSubview:buttonView];
    
        // UIButton code
        UIButton * tapMe = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [tapMe setFrame:CGRectMake(10, 10, 100, 50)];
        [tapMe setTitle:@"Tap me" forState:UIControlStateNormal];
        [tapMe setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [tapMe setBackgroundColor: [UIColor blueColor]];
        [tapMe addTarget:self action:@selector(tapButton:)      
                    forControlEvents:UIControlEventTouchUpInside];
        [buttonView addSubview:tapMe];
    }
    

    Other Possible fix You can try to add the following code after you instantiate the GMSMapView:

        GMSUISettings * settings = mapView_.settings;
        [settings setConsumesGesturesInView:NO];
    

    If there is a layer that intercepts touches, the setConsumesGesturesInView: should have the same effect as cancelsTouchesInView in that your button will still receive touch events despite being behind the GMSUISettings layer.


    What my sample looks like: