i have a map with multiple annotation on it. i was able to show the first and the last annotations. i want to give each annotation a different color.
here is my code of how to insert my annotations
if(i<1 || i >object.count-2)
{
MyAnnotation* myAnnotation1=[[MyAnnotation alloc] init];
myAnnotation1.coordinate=theCoordinate1;
myAnnotation1.title=DEVNAME;
myAnnotation1.subtitle=it.address;
[mapView addAnnotation:myAnnotation1];
[annotations addObject:myAnnotation1];
}
the if condition is reading the index of the array to only drop the first and last annotation.
and here is how do i drop the pins on the map...
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:
(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString* MyAnnotationIdentifier = #"MyAnnotationIdentifier";
MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:MyAnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorRed;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
how to different annotations color?
It is of course not going to work as except for the first and last pin, for rest of the pins, the else part of the code will execute.
So there the MKPinAnnotationView *pinView will be nil. So the annotation with no memory allocated, can not change color!!! :-)
You must alloc, init the MKPinAnnotationView *pinView for else part somewhere according to your requirement.
Use MKAnnotationView class and set a custom image for each pin:
MKAnnotationView *customPinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil];
customPinView.image = [UIImage imageNamed:#"pin1.png"];
.
.
.
instead of using images from your app bundle, you might need to programmatically build your UIImage so you can achieve unique colors, this is up to you.
Furthermore, you can set a value on your annotation to help identify which annotation gets which image. You'll subclass MKAnnotation to add this integer property called pinNumber.
myAnnotation.pinNumber = 2;
customPinView.image = [UIImage imageNamed:[NSString stringWithFormat:#"pin%d.png",annotation.pinNumber]];
Related
I have a map to which I add several annotations, like so:
for (Users *user in mapUsers){
double userlat = [user.llat doubleValue];
double userLong = [user.llong doubleValue];
CLLocationCoordinate2D userCoord = {.latitude = userlat, .longitude = userLong};
MapAnnotationViewController *addAnnotation = [[MapAnnotationViewController alloc] initWithCoordinate:userCoord];
NSString *userName = user.username;
NSString *relationship = user.relationship;
[addAnnotation setTitle:userName];
[addAnnotation setRelationshipParam:relationship];
[self.mainMapView addAnnotation:addAnnotation];
}
Using this delegate method code:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
static NSString *identifier = #"AnnotationIdentifier";
if ([annotation isKindOfClass:[MapAnnotationViewController class]]) {
MKAnnotationView *annView = (MKAnnotationView *)[self.mainMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annView) {
annView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:identifier];
}
MapAnnotationViewController *sac = (MapAnnotationViewController *)annView.annotation;
if ([sac.relationshipParam isEqualToString:#"paramA"])
{
annView.image = [UIImage imageNamed:#"image1.png"];
}
else if ([sac.relationshipParam isEqualToString:#"paramB"])
{
annView.image = [UIImage imageNamed:#"image2.png"];
}
else if ([sac.relationshipParam isEqualToString:#"paramC"])
{
annView.image = [UIImage imageNamed:#"image3.png"];
}
return annView;
}
else {
return nil;
}
This all works fine on the original loading of the map. However, when I select the annotation (which has custom code that is too long to post but includes a zoom in) the annotation images that were previously drawn have changed icons. The map is not redrawn and the annotations are not re-added in that process. When I pinch back out on the map, the images are different (they have match the incorrect relationship params with the wrong image1-3.png's.
Can anyone think of why this is happening, or what to look for?
The dequeueReusableAnnotationViewWithIdentifier may return an annotation view that was used for an annotation different from the current annotation parameter.
If the dequeueReusableAnnotationViewWithIdentifier is succesful (ie. you're using a previously-used annotation view), you must update its annotation property to be sure the view matches the current annotation's properties.
So try changing this part:
MKAnnotationView *annView = (MKAnnotationView *)[self.mainMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annView) {
annView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:identifier];
}
MapAnnotationViewController *sac = (MapAnnotationViewController *)annView.annotation;
to:
MKAnnotationView *annView = (MKAnnotationView *)[self.mainMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annView) {
annView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:identifier];
}
else {
annView.annotation = annotation; // <-- add this
}
MapAnnotationViewController *sac = (MapAnnotationViewController *)annView.annotation;
Another potential issue (not causing the problem in the question) is that the view's image property is only set if relationshipParam is one of three values.
If somehow relationshipParam is not one of those three coded values and the view was dequeued, the image will be based on some other annotation's relationshipParam.
So you should add an else part to the section that sets image and set it to some default image just in case:
...
else if ([sac.relationshipParam isEqualToString:#"paramC"])
{
annView.image = [UIImage imageNamed:#"image3.png"];
}
else
{
annView.image = [UIImage imageNamed:#"UnknownRelationship.png"];
}
I have the following code inside the delegate:
- (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id <MKAnnotation>)anAnnotation
{
MKPinAnnotationView *pin = (MKPinAnnotationView *) [map dequeueReusableAnnotationViewWithIdentifier: #"RoutePin"];
if (pin == nil)
{
if ([anAnnotation isKindOfClass:[RouteMapAnnotation class]])
{
RouteMapAnnotation *theAnnotation = (RouteMapAnnotation *)anAnnotation;
if (theAnnotation.identifier == #"routePin")
{
//NSLog(#"TESTING PART III");
MKPinAnnotationView *startAnnotationPin = [[MKPinAnnotationView alloc] initWithAnnotation:anAnnotation reuseIdentifier:#"RoutePin"];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
startAnnotationPin.canShowCallout = YES;
startAnnotationPin.animatesDrop = YES;
startAnnotationPin.rightCalloutAccessoryView = rightButton;
startAnnotationPin.pinColor = MKPinAnnotationColorRed;
return startAnnotationPin;
}
else if (theAnnotation.identifier == #"finishPin")
{
NSLog(#"CREATING FINISH FLAG PRIOR");
MKPinAnnotationView *finishAnnotationPin = [[MKPinAnnotationView alloc] initWithAnnotation:anAnnotation reuseIdentifier:#"FinishPin"];
finishAnnotationPin.canShowCallout = NO;
finishAnnotationPin.animatesDrop = YES;
//finishAnnotationPin.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://cdn4.iconfinder.com/data/icons/formula1/f1_png/128/checkered_flag.png"]]];
finishAnnotationPin.image = [UIImage imageNamed:#"flag_finish"];
return finishAnnotationPin;
}
}
}
return nil;
}
However it's not showing the image for the pin on the map. What am I missing??
You should use MKAnnotationView instead of MKPinAnnotationView.
pin annotation is for pins.
Also note that MKPinAnnotationView does offer some additional functionality to a regular MKAnnotationView, such as animating while dragging and the 3d shadow effect. You won't get these if you use MKAnnotationView.
If you want these built-in features, you can create a UIImageView and add it as a subview to your MKPinAnnotationView. This will give you an annotation that looks like whatever you want; but behaves like a pin. I use it to replace the head of the pin with my own images.
m stucked in figuring out how can i set the viewport for my google map markers.
is there any way to do it in objC??
or i have to do it in my map itself??? if yes, then how???
My code for google map just shows the maps along with the markers,but when i click it,it just shows the name of the place in a small box.. :(
how to make it a proper viewport???
here's the viewport image:
1) You can subclass MKAnnotationView. I think it's the best way to solve your problem.
2) You can customize your annotation callout view, e.g:
- (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString* ItemAnnotationIdentifier = #"itemAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
[theMapView dequeueReusableAnnotationViewWithIdentifier:ItemAnnotationIdentifier];
if (!pinView)
{
// if an existing pin view was not available, create one
MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:ItemAnnotationIdentifier]
autorelease];
customPinView.canShowCallout = YES;
UIImage *logo = [ImageProcessor scaleImage:[UIImage imageNamed:#"logo.png"] toSize:CGSizeMake(30, 30)];
customPinView.leftCalloutAccessoryView = [[[UIImageView alloc] initWithImage:logo] autorelease];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
rightButton.tag = [((ItemAnnotation *)annotation).itemId intValue];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
I figured that using my own custom pin image for annotations would be super easy.
But I have never been able to get it to work, and I have no idea why!
I am simply using:
Annotation *anno = [[[Annotation alloc] init] autorelease];
anno.coordinate = ridesMap.userLocation.location.coordinate;
anno.title = #"Current Location";
anno.subtitle = [NSString stringWithFormat:#"%f, %f", anno.coordinate.latitude, anno.coordinate.longitude];
static NSString *defaultPinID = #"LocationIdentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[ridesMap dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if (pinView == nil){
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:anno reuseIdentifier:defaultPinID] autorelease];
}
pinView.image = [UIImage imageNamed:#"custom_pin.png"];
pinView.opaque = NO;
pinView.canShowCallout = YES;
pinView.draggable = NO;
pinView.annotation = anno;
NSLog(#"Adding current location annotation");
return pinView;
I assumed that this should work, as a UIImage is what it is wanting, and I do have the custom_pin.png file in my project.
It never uses my image, but just the standard red pin. What am I doing wrong here?
From the docs:
The MKPinAnnotationView class provides a concrete annotation view that displays a pin icon like the ones found in the Maps application.
In other words, a MKPinAnnotationView will ignore the image property and always display a pin. Use a regular MKAnnotationView instead.
I'm displaying custom images on a map (instead of the default pins) using the code below. However, when I tap on an item (and the callout appears), the image reverts to the default red pin. How can I keep my custom image, even when the callout is displayed?
- (MKAnnotationView *) mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotation = nil;
if (annotation != mapView.userLocation)
{
static NSString *pinID = #"mapPin";
pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pinID];
if (pinAnnotation == nil)
pinAnnotation = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinID] autorelease];
// Set the image
pinAnnotation.image = [UIImage imageNamed:#"TestIcon.png"];
// Set ability to show callout
pinAnnotation.canShowCallout = YES;
// Set up the disclosure button on the right side
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotation.rightCalloutAccessoryView = infoButton;
[pinID release];
}
return pinAnnotation;
[pinAnnotation release];
}
I found by making the pinAnnotation a MKAnnotationView rather than a MKPinAnnotationView, I got the desired result. Image doesn't turn into a pin anymore
static NSString *pinID = #"mapPin";
pinAnnotation = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pinID];
if (pinAnnotation == nil)
pinAnnotation = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinID] autorelease];
// Set the image
pinAnnotation.image = [UIImage imageNamed:#"TestIcon.png"];
You need to use a subview rather than the image property. This code succssfully solves the problem for me:
UIImage * image = [UIImage imageNamed:#"blue_pin.png"];
UIImageView *imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
[annView addSubview:imageView];