Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To add custom View in map's Annotation's Callout's

Tags:

iphone

maps

Here is my code. I want to add my own custom callout view instead of iOS default. I know there is only left callout and right callout view, but I need to add a view tooltip type with my own background and label.

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation     {         MKAnnotationView *userAnnotationView = nil;         if ([annotation isKindOfClass:MKUserLocation.class])         {             userAnnotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"UserLocation"];             if (userAnnotationView == nil)  {             userAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"UserLocation"];             }             else                 userAnnotationView.annotation = annotation;              userAnnotationView.enabled = YES;               userAnnotationView.canShowCallout = YES;             userAnnotationView.image = [UIImage imageNamed:@"map_pin.png"];             UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0,0,141,108)];             view.backgroundColor = [UIColor clearColor];             UIImageView *imgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"toltip.png"]];             [view addSubview:imgView];             userAnnotationView.leftCalloutAccessoryView = view;                return userAnnotationView;         }  } 

Image for reference

like image 742
Gaurav Avatar asked Mar 06 '13 07:03

Gaurav


People also ask

How do you add annotations in MapKit?

We need to add the “viewFor annotation” function stub and inside the function, we need to set the annotationView, check if it is present or not, and if not create it, then we can check the annotation title and determine the image to use based on that, then return the annotationView.

What is mapview annotation?

Derived from the MKAnnotationView class, an annotation view draws the visual representation of the annotation on the map surface. Register annotation views with the MKMapView so the map view can create and efficiently reuse them.

What is MapKit in iOS?

MapKit is a powerful API available on iOS devices that makes it easy to display maps, mark locations, enhance with custom data and even draw routes or other shapes on top.

How do I annotate a map in Swiftui?

This takes three steps: Create some sort of state that will track the coordinates being shown by the map, using MKCoordinateRegion to track the center and zoom level of the map. Prepare an array of locations to use for your annotations. Decide how you want them to be shown on your map.


2 Answers

I have created a library to show custom callouts.

DXCustomCallout-ObjC

You can pass any custom view for the callout! It supports events for UIControls as well.

Custom Callout

like image 43
Selvin Avatar answered Sep 21 '22 03:09

Selvin


I had same problem and ended up doing following thing:

When I receive mapView delegate callback

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view 

(it's time when I want to show my custom CalloutView)

I use view received as parameter *(MKAnnotationView )view (which is a pin view) and simply add my custom view to that pin view using

 [view addSubview:customView]; 

It will add your custom view on top of that pin view so if we want it to be above pin we have to change custom view center property like this:

CGRect customViewRect = customView.frame;         CGRect rect = CGRectMake(-customViewRect.size.width/2, -customViewRect.size.height-7, customViewRect.size.width, customViewRect.size.height);         customView.frame = rect; [view addSubview:customView]; 

In my case it looks like this

enter image description here

!NOTE:

There is one caveat which however can be easily fixed, your custom view will ignore touch events, because of mapView working with touches differently. Here's a quick fix:

1) Subclass MKAnnotationView (or MKPinAnnotationView depends on what you need)

2) in your mapView delegate

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation 

use your subclass instead of MKAnnotationView/MKPinAnnotationView

3) in your subclass .m file override two methods as following:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event {     UIView* hitView = [super hitTest:point withEvent:event];     if (hitView != nil)     {         [self.superview bringSubviewToFront:self];     }     return hitView; }  - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {     CGRect rect = self.bounds;     BOOL isInside = CGRectContainsPoint(rect, point);     if(!isInside)     {         for (UIView *view in self.subviews)         {             isInside = CGRectContainsPoint(view.frame, point);             if(isInside)                 break;         }     }     return isInside; } 

All done!

like image 51
haawa Avatar answered Sep 23 '22 03:09

haawa