Detect tap on MK ANNOTATION view callout bubble - ios

I have an annotation on the map. When I select a annotation I will display callout bubble with custom view. Now when I click on the callout bubble I want to go to new view controller but callout view disappears when I tap on the view.
-(void)mapView:(MKMapView *)mapView1 didSelectAnnotationView:(MKAnnotationView *)view
{
NSLog(#"selected");
if(![view.annotation isKindOfClass:[MKUserLocation class]])
{
CustomInfoWindow *calloutView = [[[NSBundle mainBundle]
loadNibNamed:#"infoWindow"owner:self options:nil] objectAtIndex:0];
CGRect calloutViewFrame = calloutView.frame;
calloutViewFrame.origin = CGPointMake(-calloutViewFrame.size.width/2 + 15, -calloutViewFrame.size.height);
calloutView.frame = calloutViewFrame;
[calloutView.imagePlace.layer setBorderColor: [[UIColor orangeColor] CGColor]];
[calloutView.imagePlace.layer setBorderWidth: 3.0];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:
[NSURL URLWithString:#"http://farm3.staticflickr.com/2926/14605349699_67a1d51b80.jpg"]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
[calloutView.imagePlace setImage:image];
[view addSubview:calloutView];
}
}
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
for (UIView *subview in view.subviews ){
[subview removeFromSuperview];
}
}

I'm no expert but you may want to add a UITapGestureRecognizer to your view.
Use the following code:
UITapGestureRecognizer *tgr = [[UITabGestureRecognizer alloc] initWithTarget:self action:#selector(showNextView)];
calloutView.addGestureRecognizer(tgr);
and
- (void)showNextView {
...
}

The bubble does not have logic, you need use callout accessory. So, use MapView delegate method:
- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control;
And add callout at viewForAnnotation delegate method. For example:
UIButton *myDetailAccessoryButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
myDetailAccessoryButton.frame = CGRectMake(0, 0, 23, 23);
myDetailAccessoryButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
myDetailAccessoryButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
pinView.rightCalloutAccessoryView = myDetailAccessoryButton;
I hope my answer helps you.

Related

Add UIbutton event in custom callout view in MapView Objective C

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *view = [self.mapView dequeueReusableAnnotationViewWithIdentifier:#"loc"];
return view;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
for (MKAnnotationView *annotationView in views) {
annotationView.canShowCallout = NO;
}
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
MAKRCalloutView *calloutView = [[MAKRCalloutView alloc] initWithNibName:#"ViewM" bundle:nil];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(10.0, 10.0, 50.0, 50.0)];
[btn setBackgroundColor:[UIColor redColor]];
[btn addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:calloutView.view];
[view addSubview:btn];
}
-(void) buttonClicked:(id)sender{
NSLog(#" %ld button click %# ", (long)[sender tag]);
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
for (UIView *subview in view.subviews) {
MAKRCalloutView *calloutView = [[MAKRCalloutView alloc] initWithNibName:#"ViewM" bundle:nil];
if (![subview isKindOfClass:[calloutView.view class]]) {
continue;
}
[subview removeFromSuperview];
}
}
I cannot call get button click event. Even I cannot click on button also. I want to go at other UIViewController by click on button.
I have also tried UITapGestureRecognizer. But its limited to Pin area only.
[button addTarget:self action:#selector(clickEvent) forControlEvents:UIControlEventTouchDown]
And then
- (CustomAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[CustomAnnotation class]])
{
CustomAnnotationView *newAnnotationView = nil;
// determine the type of annotation, and produce the correct type of annotation view for it.
newAnnotationView = [[[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil delegate: targetController] autorelease];
[newAnnotationView setEnabled:YES];
[newAnnotationView setCanShowCallout:NO];
return newAnnotationView;
}
}
#interface CustomAnnotationView : MKAnnotationView
{
}
#end
#implementation CustomAnnotationView
- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier delegate:(id)targetController
{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
/* Set initial width as you want. ex: 50X50*/
self.frame = CGRectMake(0, 0, Initial_width, Initial_height);
self.backgroundColor = [UIColor redColor];
return self;
}
/* When you tap on an annotation this method is fired*/
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
if(selected){
/* When you select annotation, instead of showing default callout you can increase the width &height of annotation and add your custom view here*/
self.frame = CGRectMake(0, 0, max_width, max_height);
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(6, 0, max_width-10, max_height)];
view.backgroundColor = [UIColor blackColor];
UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *img = [UIImage imageNamed:#"image.png"];
but = CGRectMake(x , y, img.size.width + 20, img.size.height + 15);
[but setImage:img forState:UIControlStateNormal];
[but addTarget:targetController action:#selector(methodName) forControlEvents:UIControlEventTouchDown];
[view addSubview:but];
[self addSubview:view];
}
else {
/* When you tap outside of annotation, set the initial frame for the annotation. and remove the custom view from annotation*/
self.frame = CGRectMake(0, 0, Initial_width, Initial_height);
[view removeFromSuperview];
}
}

MKAnnotationView Callout Accessory

I am trying to implement a custom annotation with a custom callout view. I have successfully integrated both within my app, as you can see below:
I have created my custom callout view in a xib file:
However, when the user zooms/drags the map, my callout view stays in the same spot on the screen while the map and annotation is in a new position:
I am wondering how I can make the callout view stay above the annotation even when the map is moved, rotated or dragged. The code for my callout view can be found below:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil; //return nil to use default white dot view
}
if ([annotation isKindOfClass:[FishAnnotation class]])
{
static NSString *reuseId = #"seafoodRestaurant";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (annotationView == nil)
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
}
else
{
annotationView.annotation = annotation;
}
FishAnnotation *ann = (FishAnnotation *)annotation;
annotationView.image = [UIImage imageNamed:ann.imageName];
annotationView.draggable = YES;
annotationView.canShowCallout = NO;
return annotationView;
}
//return nil (default view) if annotation is not our custom type
return nil;
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
CalloutView *calloutView = (CalloutView *)[[[NSBundle mainBundle] loadNibNamed:#"calloutView" owner:self options:nil] objectAtIndex:0];
CGRect calloutViewFrame = calloutView.frame;
calloutViewFrame.origin = CGPointMake(view.frame.origin.x - calloutView.frame.size.width/2 + 18, view.frame.origin.y-calloutView.frame.size.height);
calloutView.frame = calloutViewFrame;
FishAnnotation *annotation = view.annotation;
[calloutView setTitle:#"Seafood Restaurant!" subTitle:#"647-123-4567"];
calloutView.annotation = view.annotation;
[view.superview addSubview:calloutView];
[view.superview bringSubviewToFront:calloutView];
}
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
for (UIView *subview in view.superview.subviews)
{
if ([subview isKindOfClass:[CalloutView class]])
{
[subview removeFromSuperview];
}
}
}
Please let me know if there is a way to have the callout view fixed above the annotation. I have tried to use
[view addSubview:calloutView];
[view bringSubviewToFront:calloutView];
instead of using view.superview, however the callout view does not display (it's hidden) if I try this.
I found a temporary solution below. The problem with this is that the buttons on my callout view no longer work. The callout disappears when I select a button.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
FishAnnotation *annotation = view.annotation;
// [appleMapView setCenterCoordinate:annotation.coordinate animated:YES];
if(![view.annotation isKindOfClass:[MKUserLocation class]])
{
CalloutView *calloutView = (CalloutView *)[[[NSBundle mainBundle] loadNibNamed:#"calloutView" owner:self options:nil] objectAtIndex:0];
CGRect calloutViewFrame = calloutView.frame;
calloutViewFrame.origin = CGPointMake(-calloutView.frame.size.width/2 + 18, -calloutView.frame.size.height);
calloutView.frame = calloutViewFrame;
[calloutView setTitle:annotation.title subTitle:annotation.subTitle];
calloutView.annotation = view.annotation;
[view addSubview:calloutView];
[view bringSubviewToFront:calloutView];
}
}
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
for (UIView *subview in view.subviews)
{
if ([subview isKindOfClass:[CalloutView class]])
{
[subview removeFromSuperview];
}
}
}
I suggest you to use this library because I've used it for my project recently.
SMCalloutView
https://github.com/nfarina/calloutview
It will help you deal with the mapView scrolling & panning.
Then I believe you can load and place your customView and addSubView inside the SMCalloutView.

custom annotation callout disappears when it's tapped

When I choose from a tableView, it goes back to my map and display the custom annotation callout over the pin selected. If I tap on another pin on the map, the custom callout view disappears from from the previous pin and is displayed over the current one selected.
If i try to tap inside the custom calloutView it also disappears. How can I avoid this, and why does this happen?
Here is the code:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if (![view.annotation isKindOfClass:[MKUserLocation class]]) {
self.calloutView = [[TNCalloutView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 150.0f, 100.0f)];
self.calloutView.alpha = 1.0f;
self.calloutView.backgroundColor = [UIColor whiteColor];
self.calloutView.layer.cornerRadius = 10.0f;
CGRect calloutViewFrame = self.calloutView.frame;
calloutViewFrame.origin = CGPointMake(-calloutViewFrame.size.width/2 + 20 , -calloutViewFrame.size.height -10);
self.calloutView.frame = calloutViewFrame;
[view addSubview:self.calloutView];
}
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[TNAnnotations class]]) {
for (UIView *subviews in view.subviews) {
[subviews removeFromSuperview];
}
}
}
If I remove the deselect method all together. Nothing ever goes away, and that's not what I want.
Also, I have checked out other posts about this very topic, but it didn't help me.
Cheers.

Custom MKAnnotation callout bubble with button

I'm developing app, where user is localized by gps and then he is asked, whether he is located in specific place. To confirm this, callout bubble is presented to him straight away, asking him, if he is at specific place.
As there is alot of similar questions, I was able to do custom callout bubble:
My problem: button is not "clickable"
My guess: because this custom callout is higher than standard callout bubble, I had to place it in negative "frame", therefore button cannot be clicked. Here is my didSelectAnnotationView method
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
if(![view.annotation isKindOfClass:[MKUserLocation class]]) {
CalloutView *calloutView = (CalloutView *)[[[NSBundle mainBundle] loadNibNamed:#"callOutView" owner:self options:nil] objectAtIndex:0];
CGRect calloutViewFrame = calloutView.frame;
calloutViewFrame.origin = CGPointMake(-calloutViewFrame.size.width/2 + 15, -calloutViewFrame.size.height);
calloutView.frame = calloutViewFrame;
[calloutView.calloutLabel setText:[(MyLocation*)[view annotation] title]];
[calloutView.btnYes addTarget:self
action:#selector(checkin)
forControlEvents:UIControlEventTouchUpInside];
calloutView.userInteractionEnabled = YES;
view.userInteractionEnabled = YES;
[view addSubview:calloutView];
}
}
CalloutView is just simple class with 2 properties(label that shows name of place and button) and with xib.
I have been doing this custom callout bubble for a few days. I tried using "asynchrony solutions" solution but I was unable to add any other kind of button then disclosure button.
My next attempt, was to find something that was easier than asynchrony solutions and modify it to my use. Thats how I found tochi's custom callout.
Based on his work, I was able to customize his bubble and change info button for my custom button. My problem however remained the same. In order to place my custom callout view on top of the pin, I had to give it negative frame, so my button was "clickable" only in bottom 5 pixels. It seems, that I have to maybe dig deeper into ios default callout bubble, subclass it and change frame of callout in there. But I'm really hopeless now.
If you guys could show me the right way, or give me advice, I'll be glad.
There are several approaches to customizing callouts:
The easiest approach is to use the existing right and left callout accessories, and put your button in one of those. For example:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *identifier = #"MyAnnotationView";
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
MKPinAnnotationView *view = (id)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (view) {
view.annotation = annotation;
} else {
view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
view.canShowCallout = true;
view.animatesDrop = true;
view.rightCalloutAccessoryView = [self yesButton];
}
return view;
}
- (UIButton *)yesButton {
UIImage *image = [self yesButtonImage];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, image.size.width, image.size.height); // don't use auto layout
[button setImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(didTapButton:) forControlEvents:UIControlEventPrimaryActionTriggered];
return button;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
That yields:
If you really don't like the button on the right, where accessories generally go, you can turn off that accessory, and iOS 9 offers the opportunity to specify the detailCalloutAccessoryView, which replaces the callout's subtitle with whatever view you want:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *identifier = #"MyAnnotationView";
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
MKPinAnnotationView *view = (id)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (view) {
view.annotation = annotation;
} else {
view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
view.canShowCallout = true;
view.animatesDrop = true;
}
view.detailCalloutAccessoryView = [self detailViewForAnnotation:annotation];
return view;
}
- (UIView *)detailViewForAnnotation:(PlacemarkAnnotation *)annotation {
UIView *view = [[UIView alloc] init];
view.translatesAutoresizingMaskIntoConstraints = false;
UILabel *label = [[UILabel alloc] init];
label.text = annotation.placemark.name;
label.font = [UIFont systemFontOfSize:20];
label.translatesAutoresizingMaskIntoConstraints = false;
label.numberOfLines = 0;
[view addSubview:label];
UIButton *button = [self yesButton];
[view addSubview:button];
NSDictionary *views = NSDictionaryOfVariableBindings(label, button);
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[label]|" options:0 metrics:nil views:views]];
[view addConstraint:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[label]-[button]|" options:0 metrics:nil views:views]];
return view;
}
- (UIButton *)yesButton {
UIImage *image = [self yesButtonImage];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = false; // use auto layout in this case
[button setImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(didTapButton:) forControlEvents:UIControlEventPrimaryActionTriggered];
return button;
}
This yields:
If you really want to develop a custom callout yourself, the Location and Maps Programming Guide outlines the steps involved:
In an iOS app, it’s good practice to use the mapView:annotationView:calloutAccessoryControlTapped: delegate method to respond when users tap a callout view’s control (as long as the control is a descendant of UIControl). In your implementation of this method you can discover the identity of the callout view’s annotation view so that you know which annotation the user tapped. In a Mac app, the callout view’s view controller can implement an action method that responds when a user clicks the control in a callout view.
When you use a custom view instead of a standard callout, you need to do extra work to make sure your callout shows and hides appropriately when users interact with it. The steps below outline the process for creating a custom callout that contains a button:
Design an NSView or UIView subclass that represents the custom callout. It’s likely that the subclass needs to implement the drawRect: method to draw your custom content.
Create a view controller that initializes the callout view and performs the action related to the button.
In the annotation view, implement hitTest: to respond to hits that are outside the annotation view’s bounds but inside the callout view’s bounds, as shown in Listing 6-7.
In the annotation view, implement setSelected:animated: to add your callout view as a subview of the annotation view when the user clicks or taps it.
If the callout view is already visible when the user selects it, the setSelected: method should remove the callout subview from the annotation view (see Listing 6-8).
In the annotation view’s initWithAnnotation: method, set the canShowCallout property to NO to prevent the map from displaying the standard callout when the user selects the annotation.
While it's in Swift, https://github.com/robertmryan/CustomMapViewAnnotationCalloutSwift illustrates an example of how you can do this complete customization of the callout (e.g. change shape of callout bubble, change background color, etc.).
That previous point outlines a pretty complicated scenarios (i.e. you have to write your own code to detecting taps outside the view in order to dismiss the it). If you're supporting iOS 9, you might just use a popover view controller, e.g.:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *identifier = #"MyAnnotationView";
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
MKPinAnnotationView *view = (id)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (view) {
view.annotation = annotation;
} else {
view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
view.canShowCallout = false; // note, we're not going to use the system callout
view.animatesDrop = true;
}
return view;
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
PopoverController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"AnnotationPopover"];
controller.modalPresentationStyle = UIModalPresentationPopover;
controller.popoverPresentationController.sourceView = view;
// adjust sourceRect so it's centered over the annotation
CGRect sourceRect = CGRectZero;
sourceRect.origin.x += [mapView convertCoordinate:view.annotation.coordinate toPointToView:mapView].x - view.frame.origin.x;
sourceRect.size.height = view.frame.size.height;
controller.popoverPresentationController.sourceRect = sourceRect;
controller.annotation = view.annotation;
[self presentViewController:controller animated:TRUE completion:nil];
[mapView deselectAnnotation:view.annotation animated:true]; // deselect the annotation so that when we dismiss the popover, the annotation won't still be selected
}
I wound up taking a different approach. I tried the others but they seemed bloated and I didn't want to add more classes or rely on the MKMapViewDelegate to handle the interaction.
I instead override setSelected:animated of my MKAnnotationView subclass. The trick is to expand the bounds of the annotationView after it it selected to fully encompass the call out view, and then return them back to normal after it is deselected. This will allow your custom call outs to accept touches and interactions outside the original bounds of the MKAnnotationView.
Here is a trimmed down code sample to get anyone started:
#define kAnnotationCalloutBoxTag 787801
#define kAnnotationCalloutArrowTag 787802
#define kAnnotationTempImageViewTag 787803
-(void)setSelected:(BOOL)selected animated:(BOOL)animated
{
if (selected == self.selected)
{
NSLog(#"annotation already selected, abort!");
return;
}
if (selected)
{
self.image = nil; //hide default image otherwise it takes the shape of the entire bounds
UIView* calloutBox = [self newCustomCallout];
float imgW = [self unselectedSize].width;
float imgH = [self unselectedSize].height;
float arrowW = 20;
float arrowH = 12;
//Annotation frames wrap a center coordinate, in this instance we want the call out box to fall under the
//central coordinate, so we need to adjust the height to be double what the callout box height would be
//making the height *2, this is to make sure the callout view is inside of it.
self.bounds = CGRectMake(0, 0, calloutBox.frame.size.width, calloutBox.frame.size.height*2 + arrowH*2 + imgH);
CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
UIView* imgView = [[UIImageView alloc] initWithImage:icon];
[imgView setFrame:CGRectMake(center.x - imgW/2, center.y-imgH/2, imgW, imgH)];
imgView.tag = kAnnotationTempImageViewTag;
[self addSubview:imgView];
UIView* triangle = [self newTriangleViewWithFrame:CGRectMake(center.x-arrowW/2, center.y+imgH/2, arrowW, arrowH)];
triangle.tag = kAnnotationCalloutArrowTag;
[self addSubview:triangle];
[calloutBox setFrame:CGRectMake(0, center.y+imgH/2+arrowH, calloutBox.width, calloutBox.height)];
calloutBox.tag = kAnnotationCalloutBoxTag;
[self addSubview:calloutBox];
}
else
{
//return things back to normal
UIView* v = [self viewWithTag:kAnnotationCalloutBoxTag];
[v removeFromSuperview];
v = [self viewWithTag:kAnnotationCalloutArrowTag];
[v removeFromSuperview];
v = [self viewWithTag:kAnnotationTempImageViewTag];
[v removeFromSuperview];
self.image = icon;
self.bounds = CGRectMake(0, 0, [self unselectedSize].width, [self unselectedSize].height);
}
[super setSelected:selected animated:animated];
}
-(CGSize)unselectedSize
{
return CGSizeMake(20,20);
}
-(UIView*)newCustomCallout
{
//create your own custom call out view
UIView* v = [[UIView alloc] initWithFrame:CGRectMake(0,0,250,250)];
v.backgroundColor = [UIColor greenColor];
return v;
}
-(UIView*)newTriangleWithFrame:(CGRect)frame
{
//create your own triangle
UIImageView* v = [[UIImageView alloc] initWithFrame:frame];
[v setImage:[UIImage imageNamed:#"trianglePointedUp.png"]];
return v;
}
(void)mapView:(MKMapView *)mapViewIn didSelectAnnotationView:(MKAnnotationView *)view {
if(![view.annotation isKindOfClass:[MKUserLocation class]])
{
CustomeCalloutViewController *calloutView = [[CustomeCalloutViewController alloc]initWithNibName:#"CustomeCalloutViewController" bundle:nil];
[calloutView setPopinTransitionStyle:BKTPopinTransitionStyleSlide];
[calloutView setPopinTransitionDirection:BKTPopinTransitionDirectionTop];
[self presentPopinController:calloutView animated:YES completion:^{
NSLog(#"Popin presented !");
}];
[mapView deselectAnnotation:view.annotation animated:true];
}
}

iOS Mapkit Custom Callout

Here's a sample custom callout that I'd want to get a similar style of. I was thinking of inheriting from MKAnnotation but I'm lost how to start it and I don't know if the callout's design could be overridden.
Any ideas how to implement this custom callout with ui controls inside?
EDIT: Here's my code from following the similar StackOverflow answer:
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView)
return annotationView;
else
{
UIImage *img = [UIImage imageNamed:#"default_thumb.png"];
MKAnnotationView *annotationView =
[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
annotationView.canShowCallout = YES;
annotationView.image = img;
annotationView.draggable = YES;
/*
// change left accessory view button with image
UIImageView *leftAccView = [[UIImageView alloc] initWithImage:img];
annotationView.leftCalloutAccessoryView = leftAccView;
//include a right button to show more info
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(calloutSubMenu:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
*/
return annotationView;
}
return nil;
}
// Customize accessory view
- (void)mapView:(MKMapView *)mapview annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
[mapview deselectAnnotation:view.annotation animated:YES];
PopOverCallout *popOverCallout = [[PopOverCallout alloc]init];
UIPopoverController *popOver = [[UIPopoverController alloc] initWithContentViewController:popOverCallout];
self.annotationPopoverController = popOver;
popOver.popoverContentSize = CGSizeMake(500, 500);
[popOver presentPopoverFromRect:view.bounds inView:view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
The
(void)mapView:(MKMapView *)mapview annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
should be called whenever the pin is touched to show the callout right? but what happens is that a blank regular callout is shown. What might I be doing wrong?
BTW: the UIViewController subclass only has a label on it's XIB and is pretty much blank.
Found out the answer after a few mins of nap.
using this as the guide, I just needed to override
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
which shows the annotation callout. Thanks again for the answer, Ms. Anna.

Resources