Adding subview to MKMapView that's above the map but below the annotation views?
Asked Answered
T

3

19

For an app I'm building, I have a custom "old map" effect PNG that I'd like to overlay on the MKMapView view. Unfortunately, neither way I've tried to do this is exactly right:

  1. Add a subview to the MKMapView (issue: the UIImageView for the PNG gets placed above the Annotation pins, which looks weird
  2. Make the image an annotation view itself and place it below the other ones (issue: on scroll, I have to move the annotation view image, and for a while there's just the regular map instead of the old-timey-effect).

What I basically want to accomplish is having a subview that is layered above the maptiles but below the annotation views, and that will hold steady while the user scrolls around—any thoughts?

Tensor answered 26/10, 2009 at 0:45 Comment(2)
Wow, old question with absolutely no answer. +1 from me as i need this tooDinesen
Has anyone figured this out yet?Agio
A
5

Note that all MKMapView subviews hierarchy, annotations, behaviour etc proceeds in internal private MKMapViewInternal class so changing anything (in a way I suggest or another) in this structure may cause your application to be rejected from Appstore.

I do not have a full solution, just an idea. My idea is to make an overlay view have the same superview as annotation views and ensure that annotations will be placed over our overlay. In MKMapViewDelegate we implement:

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{
    if (views.count > 0){
        UIView* tView = [views objectAtIndex:0];

        UIView* parView = [tView superview];
        UIView* overlay = [tView viewWithTag:2000];
        if (overlay == nil){
            overlay = [[UIImageView alloc] initWithImage:[UIImage imageNamed:MY_IMAGE_NAME]];
            overlay.frame = parView.frame; //frame equals to (0,0,16384,16384)
            overlay.tag = 2000;
            overlay.alpha = 0.7;
            [parView addSubview:overlay];
            [overlay release];
        }

        for (UIView* view in views)
            [parView bringSubviewToFront:view];
    }
}

This code does a half of what you want - you get a view placed between map tiles and annotations. The remaining task is to change custom overlay view frame according to map scrolling/zooming (I'll post if I find the way).

Attain answered 15/1, 2010 at 12:18 Comment(1)
Nice answer, this worked as well for an overlay where we wanted a gradient on the map but wanted the pins to stand out.Toothpick
D
1

I did something similar and in a different way in the end. I wanted to fade the mapview out by adding a white overlay, but I didn't want to fade the annotations. I added an overlay to the map (actually I had to add two as it didn't like me trying to add an overlay for the entire globe).

CLLocationCoordinate2D pt1, pt2, pt3, pt4;
pt1 = CLLocationCoordinate2DMake(85, 0);
pt2 = CLLocationCoordinate2DMake(85, 180);
pt3 = CLLocationCoordinate2DMake(-85, 180);
pt4 = CLLocationCoordinate2DMake(-85, 0);
CLLocationCoordinate2D coords[] = {pt1, pt2, pt3, pt4};
MKPolygon *p = [MKPolygon polygonWithCoordinates:coords count:4];
[self.mapView addOverlay:p];

pt1 = CLLocationCoordinate2DMake(85, 0);
pt2 = CLLocationCoordinate2DMake(85, -180);
pt3 = CLLocationCoordinate2DMake(-85, -180);
pt4 = CLLocationCoordinate2DMake(-85, 0);
CLLocationCoordinate2D coords2[] = {pt1, pt2, pt3, pt4};
MKPolygon *p2 = [MKPolygon polygonWithCoordinates:coords2 count:4];
[self.mapView addOverlay:p2];

Then you need to add the map delegate to draw them:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    if ([overlay isKindOfClass:MKPolygon.class]) {
        MKPolygonRenderer *polygonView = [[MKPolygonRenderer alloc] initWithOverlay:overlay];
        polygonView.fillColor = [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:0.4];
        return polygonView;
    }
    return nil;
}
Deliverance answered 17/3, 2016 at 23:19 Comment(0)
J
0

It's pretty old, but maybe still relevant for some of you.

I wanted to make the map darker, but not the annotation views.

What i did was very simple and i don't yet know if it has some fallbacks...

I put a UIView with a black-transparent background above the MKMapView, and then added the following code:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views
{
    for (MKAnnotationView *view in views) {
        view.center = [self.mapView convertCoordinate:view.annotation.coordinate toPointToView:self.viewDark];
        [self.viewDark addSubview:view];
    }
}

Hope it helps.. and of course - if you find any issues about this solution please let me know :)

Edit #1: Forgot to mention that self.viewDark should have userInteraction disabled.

Edit #2: Another thing that helped me is setting self.viewDark's autoresizesSubviews to NO.

Jefferey answered 3/1, 2016 at 10:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.