Custom Callout on MKAnnotationView - ios

I wish to show a completely custom callout view on top of the MKAnnotationView when tapped. I have stumbled through a few answers but none of them have worked and I have seen it in a few apps so I know it can be done. I would also like to show a few buttons on the callout and perform different actions upon tapping on them. I am working on Objective-C and would really appreciate any help.

You need to put your custom code on viewForAnnotation method and update view as per your requirement:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
else if ([annotation isKindOfClass:[YOUR_CUSOM_ANNO_CLASS_NAME class]]) // use whatever annotation class you used when creating the annotation
{
static NSString * const identifier = #"customAnno";
MKAnnotationView* annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView)
{
annotationView.annotation = annotation;
}
else
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:identifier];
}
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:];
return annotationView;
}
return nil;
}
There is a wonderful demo by sghiassy on github. It will help you more to understand Annotation.

Starting with iOS 9 you can use the detailCalloutAccessoryView property on MKAnnotationView. You can set this to any view. You have a Ray Wenderlich tutorial for this on Chapter 14 of iOS 9 by Tutorials.

Related

How to disable Accessibility for MKAnnotationView and Street in MKMapView

I want to disable some pins on a map view. Setting isAccessibilityElement = NO is not working on MKAnnotationView somehow.
In addition, I found VoiceOver would iterate from street to street in the map view which may not make sense in some scenarios.
So is there other way to disable the Accessibility on MKAnnotationView and the street in the map?
Current code
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) return nil;
...//some setup
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if (!annotationView && ![annotationIdentifier isEqualToString:#""]) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
}
.../some config
// somehow no effect :(
annotationView.isAccessibilityElement = NO;
return annotationView;
}

Change ONLY the bubble of information with a MKPinAnnotationView?

I want to use a normal MKPinAnnotationView, but I want to use a custom view for the callout. Every solution I can find seems to be a hack or doesn't maintain the normal dropped pin behavior
Can anyone provide an example of the simplest way to replace the callout of an MKPinAnnotationView?
You have to override the
-(MKAnnotationView*) mapView:(MKMapView *)mkMapView viewForAnnotation:(id<MKAnnotation>)annotation
function, to return a custom MKAnnotationView. In this view (that you create), you can customise the layout using the drawRect function.
This is what my custom bubble looks like:
And this is my viewForAnnotation:
-(MKAnnotationView*) mapView:(MKMapView *)mkMapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[YourAnnotation class]]) {
YourAnnotationView *yourAnnotationView = (YourAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"YourAnnotation"];
if(!yourAnnotationView)
{
yourAnnotationView = [[YourAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:#"YourAnnotation"];
}
[yourAnnotationView setTitle:annotation.title];
[yourAnnotationView setSubtitle:annotation.subtitle];
yourAnnotationView.draggable = YES;
return yourAnnotationView;
}
else
{
MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"GPXAnnotation"];
annotationView.canShowCallout = NO;
annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.draggable = YES;
return annotationView;
}
return nil;
}
Hope it can help you in the right direction!

How can i make custom pin and use FollowWithHeading mode together?

The following code below is show custom pin (picture as pin). it can use normally.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
PVAttractionAnnotationView *annotationView = [[PVAttractionAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Attraction"];
annotationView.canShowCallout = YES;
return annotationView;
}
Then use following code to show current location
[self.mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading];
XCODE jump to main.m and show
Thread 1:Signal SIGABRT
On the other hand if i use the following code
[self.mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading];
and unused all of the following code
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
PVAttractionAnnotationView *annotationView = [[PVAttractionAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Attraction"];
annotationView.canShowCallout = YES;
return annotationView;
}
Application will show current location normally but it's not show custom pin. It's show the red pin that is the default of system cause i've unused that code.
How can i make custom pin and use FollowWithHeading mode together?
..I'm sorry I do not use English well.
You need a slight change to your viewForAnnotation that examines the class of the annotation and returns the appropriate view. By returning nil the system will use the default view. You also need some additional code to implement view re-use correctly -
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *annotationView=nil;
if ([annotation isKindOfClass:[PVAttractionAnnotation class]]) // Note - put your custom annotation class here
{
annotationView =(MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"Attraction"];
if (annotationView == nil)
{
annotationView = [[PVAttractionAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Attraction"];
annotationView.canShowCallout = YES;
}
else
{
annotationView.annotation=annotation;
}
}
return annotationView;
}

setting the MKMapViewDelegate makes my marker disappear in iOS

I am using MapKit and I am having the exact problem.
This is my code:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyLocation class]]) {
MKAnnotationView *annotationView = (MKAnnotationView *) [mymap_ios dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
} else {
annotationView.annotation = annotation;
}
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
}
return nil;
}
In this code, I can see the pin but not the blue button next to it so as. It seems that I have forgotten to do this:
mymap_ios.delegate=self;
But when I add this, the marker is not shown at all.
Can you help me on that?
When you don't set the map view's delegate, it doesn't call your viewForAnnotation and creates a default red pin without any accessory buttons.
When you set the delegate, it is calling your viewForAnnotation method but you are creating a plain MKAnnotationView which by default does not have any pre-set image or view (it's blank).
Either set the annotation view's image, add some content to the view, or simply create an MKPinAnnotationView instead of an MKAnnotationView:
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [mymap_ios ...
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] init...
Also make sure that the annotation objects you add are of type MyLocation otherwise they will appear as plain red pins without an accessory button.

MapKit annotation custom image doesn't work

I have a problem with the custom image on MapKit annotation. Building a sample project where I am performing the same test, it works properly (although the drop effect and the custom image do not work).
But when I use exactly the same function on my map view project, the custom image does not appear. I noticed that the color pin change function MKPinAnnotationColorPurple does not work either. Is it possible that it depends on some project properties?
The code is:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyLocation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.animatesDrop= NO;
annotationView.image=[UIImage imageNamed:#"arrest.png" ];//here we use a nice image instead of the default pins
annotationView.canShowCallout = YES;
UIButton *btnDetails = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//[btnDetails addTarget:self action:#selector(prova) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView=btnDetails;
return annotationView;
}
return nil;
}
The UIButtonTypeDetailDisclosure does not appear either (in other projects it does).

Resources