I've been following this tutorial to show custom annotation callout bubbles.
It works perfectly if you have only one annotation with a custom annotationview.
However, I need to have more on my map, and I have troubles switching from a custom annotationview to another one. If I click on another pin when having selected already one and would like to make appear the new custom annotationview, it doesn't work. I have first to click somewhere else random on the mapview. I guess I have something to work on in DidDeselect Method, but I'm not sure...
How would you solve such a problem?
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
if (self.calloutAnnotation && [view.annotation isKindOfClass:[MyHomeAnnotation class]]) {
[self.mapView removeAnnotation: self.calloutAnnotation];
}
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
if ([view.annotation isKindOfClass:[MyHomeAnnotation class]]) {
if (self.calloutAnnotation == nil) {
self.calloutAnnotation = [[CalloutMapAnnotation alloc] initWithLatitude:view.annotation.coordinate.latitude
andLongitude:view.annotation.coordinate.longitude];
} else {
self.calloutAnnotation.latitude = view.annotation.coordinate.latitude;
self.calloutAnnotation.longitude = view.annotation.coordinate.longitude;
}
[self.mapView addAnnotation:self.calloutAnnotation];
self.selectedAnnotationView = view;
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
if (annotation == self.calloutAnnotation) {
CalloutMapAnnotationView *calloutMapAnnotationView = (CalloutMapAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:#"CalloutAnnotation"];
if (!calloutMapAnnotationView) {
calloutMapAnnotationView = [[[CalloutMapAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"CalloutAnnotation"] autorelease];
calloutMapAnnotationView.contentHeight = 78.0f;
UIImage *asynchronyLogo = [UIImage imageNamed:#"cykelrød1.png"];
UIImageView *asynchronyLogoView = [[[UIImageView alloc] initWithImage:asynchronyLogo] autorelease];
asynchronyLogoView.frame = CGRectMake(5, 2, asynchronyLogoView.frame.size.width, asynchronyLogoView.frame.size.height);
[calloutMapAnnotationView.contentView addSubview:asynchronyLogoView];
}
calloutMapAnnotationView.parentAnnotationView = self.selectedAnnotationView;
calloutMapAnnotationView.mapView = self.mapView;
return calloutMapAnnotationView;
} else if ([annotation isKindOfClass:[MyHomeAnnotation class]]) {
MKPinAnnotationView *annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"CustomAnnotation"] autorelease];
annotationView.canShowCallout = NO;
annotationView.pinColor = MKPinAnnotationColorGreen;
return annotationView;
}else if ([annotation isKindOfClass:[MyMapAnnotation class]]) {
MKPinAnnotationView *annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"NormalAnnotation"] autorelease];
annotationView.canShowCallout = YES;
annotationView.pinColor = MKPinAnnotationColorPurple;
return annotationView;
}
return nil;
}
Here are my solution, I use latitude and longitude to distinguish which callout should be remove from mapview. Hope this will be help.
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
NSLog(#"didSelectAnnotationView:%f", view.annotation.coordinate.latitude);
if (self.calloutAnnotation == nil) {
CalloutMapAnnotation *tempCallout = [[CalloutMapAnnotation alloc]
initWithLatitude:view.annotation.coordinate.latitude
andLongitude:view.annotation.coordinate.longitude];
self.calloutAnnotation = tempCallout;
[tempCallout release];
} else {
//remove callout when callout already exist
[self.myMapView removeAnnotation: self.calloutAnnotation];
self.selectedAnnotationView = nil;
//reposition
self.calloutAnnotation.latitude = view.annotation.coordinate.latitude;
self.calloutAnnotation.longitude = view.annotation.coordinate.longitude;
}
[self.myMapView addAnnotation:self.calloutAnnotation];
self.selectedAnnotationView = view;
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
NSLog(#"didDeselectAnnotationView:%f", view.annotation.coordinate.latitude);
//use the latitude and longitude to avoid remove twice
if (self.calloutAnnotation &&
self.selectedAnnotationView.annotation.coordinate.latitude == view.annotation.coordinate.latitude &&
self.selectedAnnotationView.annotation.coordinate.longitude == view.annotation.coordinate.longitude
) {
[self.myMapView removeAnnotation: self.calloutAnnotation];
self.selectedAnnotationView = nil;
self.calloutAnnotation.isAddtoMap = NO;
}
}
Related
I have dot as a pin annotation in map and showing custom annotation view.My problem is that when I click on dot sometimes dot behinds custom annotation view comes in fron of custom annotation view instead of showing behind it.
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKAnnotationView *annotationView;
PinAnnotationView *pinView = nil;
NSString *identifier;
if ([annotation isKindOfClass:[DisplayMap class]])
{
identifier = #"Pin";
NSInteger myid = ((DisplayMap *)annotation).takeid;
MKAnnotationView *pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
DisplayMap *a = (DisplayMap *)annotation;
pinView.annotation=a;
if (myid == 1)
{
UIImage *test = [UIImage imageNamed:#"red_dot.png"];
pinView.image = test;
pinView.opaque = NO;
}
else if (myid == 2)
{
UIImage *test = [UIImage imageNamed:#"blue_dot.png"];
pinView.image = test;
pinView.opaque = NO;
}
else {
UIImage *test = [UIImage imageNamed:#"green_dot.png"];
pinView.image = test;
pinView.opaque = NO;
}
return pinView;
}
else if ([annotation isKindOfClass:[CalloutAnnotation class]])
{
identifier = [NSString stringWithFormat:#"Callout%d",pinView.tag];
annotationView = [[CalloutAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
CalloutAnnotation *calloutAnnotation = (CalloutAnnotation *)annotation;
((CalloutAnnotationView *)annotationView).title = calloutAnnotation.title;
((CalloutAnnotationView *)annotationView).iTag = calloutAnnotation.iTag;
[annotationView setNeedsDisplay];
[UIView animateWithDuration:0.5f
animations:^(void) {
mapView.centerCoordinate = calloutAnnotation.coordinate;
}];
annotationView.annotation = annotation;
return annotationView;
}
}
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view1
{
if ([view1.annotation isKindOfClass:[DisplayMap class]])
{
DisplayMap *pinAnnotation = ((DisplayMap *)view1.annotation);
LoginDetail *obj = [[appDelegate mapArray] objectAtIndex:pinAnnotation.iTag];
[mapView removeAnnotations:annotationRemoveArray];
CalloutAnnotation *calloutAnnotation = [[CalloutAnnotation alloc] init];
calloutAnnotation.title = pinAnnotation.title;
pinAnnotation.calloutAnnotation = calloutAnnotation;
[mapView addAnnotation:calloutAnnotation];
[annotationRemoveArray addObject:calloutAnnotation];
[self setzoomonselectannotation:pinAnnotation.coordinate];
}
}
The callout window is an annotation view as well. That is wrong ;)
follow one the hints:
How to customize the callout bubble for MKAnnotationView?
Basically what they say: make the callout a subview of the pin itself
I would like to know how to change the pin color of an annotation in map kit. Currently Im using the following code.
//King Solomon's Lodge No. 194
CLLocationCoordinate2D kingsolomons;
kingsolomons.latitude = 38.052041;
kingsolomons.longitude = -78.683218;
Annotation *kingsolomonslodge = [[Annotation alloc] init];
kingsolomonslodge.coordinate = kingsolomons;
kingsolomonslodge.title = #"King Solomon's Lodge No. 194";
kingsolomonslodge.subtitle = #"Charlottesville, VA";
[self.myMapView addAnnotation:kingsolomonslodge];
I have googled this question a few times but Im unsure on how to implement this into the current code that I have.
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
if (annotation == mapview.userLocation)
return nil;
MKPinAnnotationView *pin = (MKPinAnnotationView *) [mapview dequeueReusableAnnotationViewWithIdentifier: #"asdf"];
if (pin == nil)
pin = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier: #"asdf"] autorelease];
else
pin.annotation = annotation;
// NSLog(#"%#",annotation.title);
NSString *titlename=#"xyz";
if ([annotation.title isEqualToString:titlename]) {
pin.pinColor = MKPinAnnotationColorGreen;
// pin.image=[UIImage imageNamed:#"arrest.png"] ;
}
else{
pin.pinColor= MKPinAnnotationColorPurple;
}
pin.userInteractionEnabled = YES;
UIButton *disclosureButton = [UIButton buttonWithType:UIButtonTypeCustom];
// //pin.image=[UIImage imageNamed:#"arrest.png"] ;
pin.rightCalloutAccessoryView = disclosureButton;
//pin.pinColor = MKPinAnnotationColorRed;
pin.animatesDrop = YES;
[pin setEnabled:YES];
[pin setCanShowCallout:YES];
return pin;
}
You can use pinColor property if MKAnnotation class.
kingsolomonslodge.pinColor = MKPinAnnotationColorGreen;
Another way is you can use image instead of the default pin using viewForAnnotation: delegate:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[yourAnnotationLocation class]])
{
MKAnnotationView *annotationView = (MKAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil)
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"yourImage.png"];//here we use a nice image instead of the default pins
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
else
{
annotationView.annotation = annotation;
}
return annotationView;
}
return nil;
}
try this man...
kingsolomonslodge.pinColor = AnnotationColorRed;
let me know whether it is workihg or not
happy coding!!!!
If you want to apply custom color you can add image also.
MKAnnotationView *pinView = nil;
pinView.image = [UIImage imageNamed:#"pinks.jpg"];
Since iOS 9:
kingsolomonslodge.pinTintColor = UIColor.greenColor;
The default pin drop animation doesn't work in my app, here is some code I wrote:
- (void)viewDidLoad {
/*
some code...
*/
[theMapView addAnnotation:addAnnotation];
[addAnnotation release];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
MKPinAnnotationView *annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"current"];
annoView.animatesDrop = YES;
annoView.pinColor = MKPinAnnotationColorGreen;
return annoView;
}
Right now the pin just appear in the screen as default red one without any animation, the MKMapViewDelegate protocol has been adopted, anyone can see what's wrong here?
First use:
[yourMap_view setDelegate:self];
in ViewDidLoad
Then call this for the drop animation :
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinView = nil;
if(annotation!= map_view.userLocation)
{
static NSString *defaultPin = #"pinIdentifier";
pinView = (MKPinAnnotationView*)[map_view dequeueReusableAnnotationViewWithIdentifier:defaultPin];
if(pinView == nil)
pinView = [[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:defaultPin]autorelease];
pinView.pinColor = MKPinAnnotationColorPurple; //Optional
pinView.canShowCallout = YES; // Optional
pinView.animatesDrop = YES;
}
else
{
[map_view.userLocation setTitle:#"You are Here!"];
}
return pinView;
}
Hi can some1 plz help me....
The problem is this: Everything seems alright.. i am able to push to another page once i tap on the detailButton. However, the page which i am able to push to is always only a view without any values passed into the labels. All my labels in the view have nothing inside.. Am i doing something wrong or any wrong concept here?
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
BOOL isRed = NO;
//BOOL isPurple = YES;
if([annotation isKindOfClass:[MyAnnotation2 class]])
isRed = YES;
MKPinAnnotationView *pinView = nil;
if(isRed) {
static NSString *redPin = #"redPin";
pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:redPin];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:redPin] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = detailButton;
}
else{
pinView.annotation = annotation;
}
}
else {
static NSString *greenPin = #"greenPin";
pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:greenPin];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:greenPin] autorelease];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = detailButton;
}
}
return pinView;
}
//
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"calloutAccessoryControlTapped");
if (self.patientDetailsViewController == nil) {
self.patientDetailsViewController = [[[PatientDetailsViewController alloc] initWithNibName:#"PatientDetailsViewController" bundle:nil] autorelease];
}
MyAnnotation2 *selectedObject = (MyAnnotation2 *)view.annotation;
_patientDetailsViewController.nric = selectedObject.title;
NSLog(#"%#",_patientDetailsViewController.nric);
[self.navigationController pushViewController:_patientDetailsViewController animated:YES];
}
Don't use your own target/action and tagging for the callout accessory button.
Instead, use the MKMapViewDelegate method calloutAccessoryControlTapped:. Remove the addTarget line and implement the delegate method.
In that delegate method, you can access the annotation tapped using:
MyAnnotation2 *selectedObject = (MyAnnotation2 *)view.annotation;
My MKMapView shows my position at startup but then the image never 'follows' me. The location gets updated and the screen does follow me, but the original "User Location" image stays behind.
Here is some code snippets:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(!pinView)
{
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
if(annotation == mapView.userLocation) customPinView.image = [self rotate:[UIImage imageNamed:#"myCar.png"] orientation:UIImageOrientationUp];
else customPinView.image = [UIImage imageNamed:#"randomPin.png"];
customPinView.animatesDrop = NO;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
-(void)locationUpdate:(CLLocation *)location
{
CLLocationCoordinate2D loc = [location coordinate];
if(isFollowing)
[myMapView setCenterCoordinate:loc];//Works
}
and in my viewDidLoad I do call: [myMapView setShowsUserLocation:YES]; which does work.
So basically somewhere I neglect updating my position or its most possibly where I draw the new image for my current position.
Can anyone possibly see what I am missing or doing wrong there for it to not follow my location updates?
Thanks.
It's not clear if this is the issue but the viewForAnnotation method doesn't look right.
The annotation image is only being set when an annotation view is created. If a view is re-used, the annotation property is updated but not the image. It's possible that the re-used view is for an annotation of a different type requiring a different image.
The method should look something like this:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
{
pinView.annotation = annotation;
}
if (annotation == mapView.userLocation)
pinView.image = [self rotate:[UIImage imageNamed:#"myCar.png"] orientation:UIImageOrientationUp];
else
pinView.image = [UIImage imageNamed:#"randomPin.png"];
return pinView;
}