Add buttons to view returned by markerInfoWindow delegate method

后端 未结 5 735
逝去的感伤
逝去的感伤 2020-11-28 08:00

I\'m currently creating and returning a custom view with the google maps ios SDK by setting delegate to self and using the following code.

#pragma mark - GMS         


        
相关标签:
5条回答
  • 2020-11-28 08:11

    UPDATE:

    Here is the code I use in order to detect tap on buttons added to my infoWindows. I create a custom infoWindow with 2 fake buttons (they could actually replaced by images because they won't trigger any action) and I add a completely transparent overlay with 2 real buttons over the infoWindow. These buttons will trigger the actions.

    And I use a few delegate methods or KVC in order to move the overlay when the infoWindow itself is moved.

    - (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
        [self.actionOverlayCalloutView removeFromSuperview];
        UIView *calloutView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, infoWindowWidth, infoWindowHeight)];
    
        float offset = anchorSize * M_SQRT2;
        CGAffineTransform rotateBy45Degrees = CGAffineTransformMakeRotation(M_PI_4);
        UIView *arrow = [[UIView alloc] initWithFrame:CGRectMake((infoWindowWidth - anchorSize)/2.0, infoWindowHeight - offset, anchorSize, anchorSize)];
        arrow.transform = rotateBy45Degrees;
        arrow.backgroundColor = [UIColor lightGrayColor];
        [calloutView addSubview:arrow];
    
        UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, infoWindowWidth, infoWindowHeight - offset/2)];
        [contentView setBackgroundColor:[UIColor whiteColor]];
    
        contentView.layer.cornerRadius = 5;
        contentView.layer.masksToBounds = YES;
    
        contentView.layer.borderColor = [UIColor lightGrayColor].CGColor;
        contentView.layer.borderWidth = 1.0f;
    
        self.actionOverlayCalloutView =
        [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:contentView]]; //hack to copy a view...
        self.actionOverlayCalloutView.backgroundColor = [UIColor lightGrayColorWithAlpha:0.5];
        self.actionOverlayCalloutView.layer.cornerRadius = 5;
        NSMutableArray *falseButtons = [NSMutableArray array];
        NSMutableArray *actionButtons = [NSMutableArray array];
        PointMapItem *pointAnnotation = marker.userData;
        if ([pointAnnotation canPerformSend]) {
            UIButton *button = [[UIButton alloc] init];
            [button setImage:[UIImage imageNamed:@"imageButton1.png"] forState:UIControlStateNormal];
            [falseButtons addObject:button];
            UIButton *activableButton = [[UIButton alloc] init];
            [activableButton addTarget:self action:@selector(onButton1Clicked) forControlEvents:UIControlEventTouchUpInside];
            [actionButtons addObject:activableButton];
        }
        if ([pointAnnotation canPerformShowDetails]) {
            UIButton *button = [[UIButton alloc] init];
            [button setImage:[UIImage imageNamed:@"imageButton1.png"] forState:UIControlStateNormal];
            [falseButtons addObject:button];
            UIButton *activableButton = [[UIButton alloc] init];
            [activableButton addTarget:self action:@selector(onButton2Clicked) forControlEvents:UIControlEventTouchUpInside];
            [actionButtons addObject:activableButton];
        }
        int buttonWidth = contentView.frame.size.width / [falseButtons count];
        int currentOffset = 0;
        for (int i=0; i<falseButtons.count; i++) {
            UIButton *falseButton = [falseButtons objectAtIndex:i];
            UIButton *activableButton = [actionButtons objectAtIndex:i];
            [falseButton setFrame:CGRectMake(currentOffset, 0, buttonWidth, contentView.frame.size.height)];
            currentOffset += buttonWidth;
            activableButton.frame = falseButton.frame;
            [activableButton setTitle:@"" forState:UIControlStateNormal];
            [self.actionOverlayCalloutView addSubview:activableButton];
            [contentView addSubview:falseButton];
        }
        [calloutView addSubview:contentView];
    
        CLLocationCoordinate2D anchor = [self.mapView.selectedMarker position];
        CGPoint point = [self.mapView.projection pointForCoordinate:anchor];
        point.y -= self.mapView.selectedMarker.icon.size.height + offset/2 + (infoWindowHeight - offset/2)/2;
        self.actionOverlayCalloutView.center = point;
    
        [self.mapView addSubview:self.actionOverlayCalloutView];
        return calloutView;
    }
    
    - (void)mapView:(GMSMapView *)pMapView didChangeCameraPosition:(GMSCameraPosition *)position {
        if (pMapView.selectedMarker != nil && self.actionOverlayCalloutView.superview) {
            CLLocationCoordinate2D anchor = [self.mapView.selectedMarker position];
            CGPoint point = [self.mapView.projection pointForCoordinate:anchor];
            float offset = anchorSize * M_SQRT2;
            point.y -= self.mapView.selectedMarker.icon.size.height + offset/2 + (infoWindowHeight - offset/2)/2;
            self.actionOverlayCalloutView.center = point;
        } else {
            [self.actionOverlayCalloutView removeFromSuperview];
        }
    }
    
    - (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
        [self.actionOverlayCalloutView removeFromSuperview];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if ([keyPath isEqualToString:@"mapView.selectedMarker"]) {
            if (!self.mapView.selectedMarker) {
                [self.actionOverlayCalloutView removeFromSuperview];
            }
        }
    }
    
    - (void)onButton2Clicked {
        //your code
        self.mapView.selectedMarker = nil;
    }
    
    - (void)onButton1Clicked {
        // your code;
        self.mapView.selectedMarker = nil;
    }
    

    FORMER POST:

    Have a look at this thread and specifically at #9, should be helpful https://code.google.com/p/gmaps-api-issues/issues/detail?id=4961

    0 讨论(0)
  • 2020-11-28 08:16

    1)Create one subview which you want to show in infoWindow.

    2)Set frame of subview equals to frame of infoWindow view.

      [subView setFrame:infoview.frame];
      subView =  [[[NSBundle mainBundle] loadNibNamed:@"viewName" owner:self options:nil] objectAtIndex:0];
      [self.mapview addSubview:subView];
    
    0 讨论(0)
  • 2020-11-28 08:17

    Swift 3.0 Solution

     //empty the default infowindow
            func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
                return UIView()
            }
    
            // reset custom infowindow whenever marker is tapped
            func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    
                customInfoView.removeFromSuperview()
            //    customInfoView.button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
                self.view.addSubview(customInfoView)
    
                // Remember to return false
                // so marker event is still handled by delegate
                return false
            }
    
            // let the custom infowindow follows the camera
            func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
                if (locationMarker != nil){
                    let location = locationMarker.position
                    customInfoView.center = mapView.projection.point(for: location)
                }
            }
    
            // take care of the close event
            func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
                customInfoView.removeFromSuperview()
            }
    

    and make outlet of this view(customInfoWindow) in same controller which has mapView.

    I got the idea from this link thanks to this developer Custom and interactive googlemaps(IOS SDK) infowindow

    0 讨论(0)
  • 2020-11-28 08:23

    I have a UView and I'm adding a delegate to the view so that a UIButton calls a selector. For the google map, I don't do anything when I call

    - (void) mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker;
    

    However, I set my infowindow (my custom view) delegate to self, and call all my actions when I press the button that's linked to the selector.

    0 讨论(0)
  • 2020-11-28 08:34

    Possibly, as mentioned officially in documentation of Google Maps Android API, the below restriction regarding infowindows applies to Google Maps iOS SDK also :

    Info window is not a live View, rather the view is rendered as an image onto the map. As a result, any listeners you set on the view are disregarded and you cannot distinguish between click events on various parts of the view. You are advised not to place interactive components — such as buttons, checkboxes, or text inputs — within your custom info window.

    So basically clicking on any part of the infowindow will trigger only "didTapWindowOfMarker"

    0 讨论(0)
提交回复
热议问题