Custom annotation view in Google Maps SDK

前端 未结 2 1585
谎友^
谎友^ 2020-11-30 09:32

I created an iOS application based on maps in which I thought to use Google Maps SDK for iOS instead of Mapkit, I found the documentation but it I didn’t find methods relate

相关标签:
2条回答
  • 2020-11-30 10:01

    If you check GMSMapView.h within GoogleMaps.Framework, you can see the below method which should let you add a custom infowindow for a marker, instead of using standard title and snippet alone:

    NOTE you (op) say annotationView=infoWindow
    BUT NORMAL: annotationView = marker itself and calloutView = infoWindow

    /**
     * Called when a marker is about to become selected, and provides an optional
     * custom info window to use for that marker if this method returns a UIView.
     * If you change this view after this method is called, those changes will not
     * necessarily be reflected in the rendered version.
     *
     * The returned UIView must not have bounds greater than 500 points on either
     * dimension.  As there is only one info window shown at any time, the returned
     * view may be reused between other info windows.
     *
     * @return The custom info window for the specified marker, or nil for default
     */
    - (UIView *)mapView:(GMSMapView *)mapView
        markerInfoWindow:(id<GMSMarker>)marker;
    
    0 讨论(0)
  • 2020-11-30 10:15

    I don't know about y'all, but I find Google's rendered UIView info windows to be a bit restricting. Using SMCalloutView and Ryan Maxwell's example project, it's possible to present more interactive views.

    This works on Google Maps SDK v1.8.1, as of 2014-June-10.

    Default SMCalloutView on Google Maps

    First, do some set up:

    #import <SMCalloutView/SMCalloutView.h>
    
    static const CGFloat CalloutYOffset = 10.0f;
    
    @interface ViewController ()
    @property (strong, nonatomic) SMCalloutView *calloutView;
    @property (strong, nonatomic) UIView *emptyCalloutView;
    @end
    

    Initialize SMCalloutView, add a button to it, then create an empty UIView:

    - (void)viewDidLoad
    {
        /* all your other view init, settings, etc... */
    
        self.calloutView = [[SMCalloutView alloc] init];
        self.calloutView.hidden = YES;
    
        UIButton *button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [button addTarget:self
                   action:@selector(calloutAccessoryButtonTapped:)
         forControlEvents:UIControlEventTouchUpInside];
        self.calloutView.rightAccessoryView = button;
    
        self.emptyCalloutView = [[UIView alloc] initWithFrame:CGRectZero];
    }
    

    We have to draw that empty UIView to satisfy the Maps SDK, but the view we will display is SMCalloutView. I also set a reuseable vertical offset for the callout view.

    Add delegate methods to handle info window calls:

    #pragma mark - GMSMapViewDelegate
    
    - (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
        CLLocationCoordinate2D anchor = marker.position;
    
        CGPoint point = [mapView.projection pointForCoordinate:anchor];
    
        self.calloutView.title = marker.title;
    
        self.calloutView.calloutOffset = CGPointMake(0, -CalloutYOffset);
    
        self.calloutView.hidden = NO;
    
        CGRect calloutRect = CGRectZero;
        calloutRect.origin = point;
        calloutRect.size = CGSizeZero;
    
        [self.calloutView presentCalloutFromRect:calloutRect
                                          inView:mapView
                               constrainedToView:mapView
                                        animated:YES];
    
        return self.emptyCalloutView;
    }
    
    - (void)mapView:(GMSMapView *)pMapView didChangeCameraPosition:(GMSCameraPosition *)position {
        /* move callout with map drag */
        if (pMapView.selectedMarker != nil && !self.calloutView.hidden) {
            CLLocationCoordinate2D anchor = [pMapView.selectedMarker position];
    
            CGPoint arrowPt = self.calloutView.backgroundView.arrowPoint;
    
            CGPoint pt = [pMapView.projection pointForCoordinate:anchor];
            pt.x -= arrowPt.x;
            pt.y -= arrowPt.y + CalloutYOffset;
    
            self.calloutView.frame = (CGRect) {.origin = pt, .size = self.calloutView.frame.size };
        } else {
            self.calloutView.hidden = YES;
        }
    }
    
    - (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
        self.calloutView.hidden = YES;
    }
    
    - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
        /* don't move map camera to center marker on tap */
        mapView.selectedMarker = marker;
        return YES;
    }
    

    Handle touches on the callout button, here using an alert view with marker title and snippet:

    - (void)calloutAccessoryButtonTapped:(id)sender {
        if (mapView_.selectedMarker) {
            GMSMarker *marker = mapView_.selectedMarker;
            //NSDictionary *userData = marker.userData;
    
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:marker.title
                                                                message:marker.snippet
                                                               delegate:nil
                                                      cancelButtonTitle:@"OK"
                                                      otherButtonTitles:nil];
            [alertView show];
        }
    }
    

    Obviously, make sure your ViewController(.h) listens to GMSMapViewDelegate:

    @interface ViewController : UIViewController <GMSMapViewDelegate>
    

    And that should basically work. For a complete xcode project, see the aforementioned example from Ryan Maxwell.

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