How to create a callout bubble MKAnnotationView that respond to touches - iphone

I'm trying to make a custom annotation view able to respond to touches without success.
Thanks to this question I was able to made an annotation view close to what I want customize callout bubble for annotationview? also seen this How to capture touches and NOT dismiss the callout? but the problem is quite different
The first thing I've done so far is subclassing an MKAnnotationView and override the -setSelected:animated: method
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if(selected)
{
MyCallOut * callOut=[MyCallOut createMyCallOut];
callOut.tag=555;
[self.superview addSubview:callOut];
}
else
{
// [[self viewWithTag:555] removeFromSuperview];
//Remove my custom CallOut
}
}
The problem is that the map view is eating all the touches event, my custom callout has two buttons but no action is triggered pressing them.
In one of my experiment I've tried to add the callout view to the MKAnnotationView superview (the mapView) everything seems to be fine while I scroll, but If I zoom the callout moves around.

you have to add call out accessory view in map annotation
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return pinView;
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
and for click event of your call out
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
}

Solved looking to this link Custom annotation and callouts, the other tricky part is implement a correct way to press button on the fake callout. I managed this part creating a boolean value that understands the number of annotation/parentAnnotation on screen and choose when one could disappear or not.Just need to make the CalloutAnnotation available to selection.

Related

Disable MKPlacemark showing/hiding title in iPhone

I have MKMapView with MKPlacemark on it. When showing the map, I'm showing place mark's title.
Everything is fine until now.
I want to disable hiding title when user touches it.
I tried to add
myMapView.userInteractionEnabled = NO;
myMapView.multipleTouchEnabled = NO;
Which helps, but completely disables interaction with map. I want to leave a possibility to zoom in/out and moving the map.
Instead of creating PIN, create your custom annotation. In custom annotation create the view with all the info that you want to present to user, and disable the place mark. By that you are not suppose to handle taps but you will show all the static/dynamic info attached to one lattitude/longitude.
The following code did the trick
for (UIGestureRecognizer *g in [myMapView gestureRecognizers])
[myMapView removeGestureRecognizer:g];
In MapKit Delegate method try bellow code
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *defaultPinID = #"com.invasivecode.pin";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[yourMapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
if (annotation == yourMapview.userLocation)
return nil;
pinView.pinColor = MKPinAnnotationColorRed;
pinView.userInteractionEnabled = NO;
//pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
return pinView;
}
here if you use your placemark with this logic may its work....
hope,this help you...
:)

Custom annotation pin changes to default red pin at long tap

I have custom annotation pin at app:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
return [kml viewForAnnotation:annotation type:state];
}
where I return custom view and make setImage for annotationView of Placemark such as:
- (MKAnnotationView *)viewForAnnotation:(id <MKAnnotation>)point type:(int)state
{
// Find the KMLPlacemark object that owns this point and get
// the view from it.
for (KMLPlacemark *placemark in _placemarks) {
if ([placemark point] == point)
{
UIButton *disclosureButton = [UIButton buttonWithType: UIButtonTypeDetailDisclosure];
[[placemark annotationView] setCanShowCallout: YES];
[[placemark annotationView] setRightCalloutAccessoryView:disclosureButton];
if (state == 0)
{
[[placemark annotationView] setImage:[UIImage imageNamed:#"ic_pin_tour.png"]];
}
else
{
[[placemark annotationView] setImage:[UIImage imageNamed:#"ic_pin_point.png"]];
}
return [placemark annotationView];
}
}
return nil;
}
but if I long tap at my annotation pin it changes appearance to its default view (RedPin).
I cannot understand what method is called on long tap. I tried to play with UITapGestureRecognizer, but did not find out. If I just tap annotation pin all works fine and my custom annotation pin view doesn't disappear.
You can see what I mean in this screenshot:
So, why annotation pin appearance changes on long tap?
So, if you want to use a custom image for an annotation view, always use a generic MKAnnotationView instead of an MKPinAnnotationView.
I have MKPinAnnotationView at just one place, when I replace it with MKAnnotationView everything works properly now:
- (MKAnnotationView *)annotationView
{
if (!annotationView) {
id <MKAnnotation> annotation = [self point];
if (annotation) {
MKAnnotationView *pin =
[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil];
pin.canShowCallout = YES;
annotationView = pin;
}
}
return annotationView;
}

DetailDisclosure button not showing in annotation view

For some odd reason the detail button somehow stopped appearing:
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotation = nil;
if(annotation != mapView.userLocation)
{
MKPinAnnotationView *pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"sadasdasd"];
if ( pinAnnotation == nil ){
pinAnnotation = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"sadasdasd"] autorelease];
/* add detail button */
NSLog(#"Here");
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotation.rightCalloutAccessoryView = infoButton;
}
}
return pinAnnotation;
}
Here is output.
Thanks in advance.
First problem is that pinAnnotation is declared twice in that method.
Once in the first line and second in the if(annotation != mapView.userLocation)... block. Because of this, the return statement returns nil because the outer variable is never set (resulting in a default MKAnnotationView callout with no accessory).
Change the second declaration to just an assignment.
Next problem is that you need to set canShowCallout to YES because the default is NO for an MKPinAnnotationView. You can do this after setting the accessory view:
pinAnnotation.canShowCallout = YES;
The above should fix the accessory button not showing.
Unrelated, but you also need to set the view's annotation property when it is being re-used (in the case when it is not nil after the dequeue). So add an else block to the if (pinAnnotation == nil):
else {
//annotation view being re-used, set annotation to current...
pinAnnotation.annotation = annotation;
}

Change Pin Color when user tapped

I would change the color from red to green of an annotation when the user pin tapped addition to changing its title and subtitle.
I am truly lost. I searched how to make a custom annotation pin, ok. I found the implementation of the method when the user touches the pin didSelectAnnotationView and it works when I tap the annotation NSLog(#"Tap") ; , but now I can not change the pin that was touched.
Thank you very much everyone for your contributions.
Ciao
To set the pin color, make use of MKPinAnnotationView pinColor property.
MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] init]
pin.pinColor = MKPinAnnotationColorGreen;
For custom annotation image, set the image property, as such.
UIImage *annImage = [UIImage imageNamed:#"AnnotationIcon.png"];
annView.image = annImage;
Do note that the MKPinAnnotationView animateDrop property will not work on custom images. There's a way to duplicate that animation though. See How do I animate MKAnnotationView drop?
Update
So bascially, you do this if you wanna change from red to green upon being selected.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorGreen;
}
- (MKAnnotationView *)mapView:(MKMapView *)aMapView
viewForAnnotation:(id)ann {
NSString *identifier = #"myPin";
MKPinAnnotationView *annView = (MKPinAnnotationView *)
[aMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annView == nil) {
annView= [[[MKPinAnnotationView alloc] initWithAnnotation:ann
reuseIdentifier:identifier]
autorelease];
} else {
annView.annotation = ann;
}
// you can define the properties here.
return annView;
}
In your method set the pinColor property of your MKAnnotationView as follows:
annotationView.pinColor = MKPinAnnotationColorRed; // Green or Purple
(re) look this :
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view {
view.pinColor = MKPinAnnotationColorGreen;
}
this is a MKPinAnnotationView (and not MKAnnotationView) in param

Monotouch MapKit - annotations - adding a button to bubble

Anyone know if there's anyway to get a button onto an annotation?
I'd like the location to be selectable - so you can say.. select the location and get all the events at that location by clicking on the button.
is this possible?
w://
Here's the code I used for my annotation, it includes a button on the right side of the bubble. You can set an IBAction to push a new view onto the stack to display whatever you want
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotation = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"myPin";
pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinAnnotation == nil )
pinAnnotation = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinAnnotation.canShowCallout = YES;
//instatiate a detail-disclosure button and set it to appear on right side of annotation
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotation.rightCalloutAccessoryView = infoButton;
}
return pinAnnotation;
}
I just helped someone else with this in objective c, but I'm sure the concept is the same with mono. You need to create a custom MKAnnotationView object and override the GetViewForAnnotation (viewForAnnotation in obj-c) method of your MKMapViewDelegate class... check out the other question.
When you create your custom MKAnnotationView object it is basically a UIView made for map annotations... you can just add your button and other info to the view and it will show up when the user hits the annotation.
Here some rough code for the delegate method:
public override MKAnnotationView GetViewForAnnotation(
MKMapView mapView,NSObject annotation) {
var annotationId = "location";
var annotationView = mapView.DequeueReusableAnnotation(annotationId);
if (annotationView == null) {
// create new annotation
annotationView = new CustomAnnotationView(annotation, annotationId);
}
else {
annotationView.annotation = annotation;
}
annotation.CanShowCallout = true;
// setup other info for view
// ..........
return annotationView;
}
}