I'm building an app using swift and MapKit. It has several custom point annotations. I would like to display the title above all annotations at any time, by default. Hence they would be all selected. Therefore I could get inspiration from this post and use:
[mapView selectAnnotation:pinView animated:YES]
But I still need to be able to select a pin by clicking on it and get a new mapScope based on this annotation. How could I do it?
If the first solution is not possible, I would use a specific label on each annotation. But then is there a way to hide the annotation title forever?
EDIT:
Here is the code for the custom point annotation:
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
println("viewForAnnotation")
if !(annotation is MKPointAnnotation) {
return nil
}
var seleccion:Bool
let cpa = annotation as! CustomPointAnnotation
let reuseId = cpa.nickName as String
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
// create and add UILabel only when actually creating MKAnnotationView
var nameLbl: UILabel! = UILabel(frame: CGRectMake(-24, 40, 100, 30))
nameLbl.tag = 42
nameLbl.textColor = UIColor.blackColor()
nameLbl.font = UIFont(name: "Atari Classic Extrasmooth", size: 10)
nameLbl.textAlignment = NSTextAlignment.Center
anView.addSubview(nameLbl)
}
else {
anView.annotation = annotation
}
anView.image = cpa.image
if cpa.toBeTriggered == true {
anView.selected = true
}
if let nameLbl = anView.viewWithTag(42) as? UILabel {
nameLbl.text = cpa.nickName
}
return anView
}
As you are using custom annotation views this code will be helpful to you.
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation //thammu
{
static NSString *reuseId = #"StandardPin";
MKAnnotationView *aView;
//MKAnnotationView *aView = (MKAnnotationView *)[Mapsview dequeueReusableAnnotationViewWithIdentifier:reuseId];
aView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:reuseId];
aView.enabled = YES;
aView.canShowCallout = YES;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
UIImageView *img=[[UIImageView alloc]initWithFrame:CGRectMake(-41,-22,121,25)];
img.image=[UIImage imageNamed:#"annotation-bg#2x.png"]; //This is the Details image view
UILabel *lblPlaceholder1=[[UILabel alloc]init];
lblPlaceholder1 = [[UILabel alloc]initWithFrame:CGRectMake(4,2,117, 21)];
lblPlaceholder1.backgroundColor=[UIColor clearColor];
lblPlaceholder1.numberOfLines=1;
[lblPlaceholder1 setTextColor:[UIColor redColor]];
lblPlaceholder1.textAlignment=NSTextAlignmentCenter;
lblPlaceholder1.text=annotation.title;
[lblPlaceholder1 setTextColor:[UIColor darkGrayColor]];
[lblPlaceholder1 setFont:[UIFont fontWithName:#"Roboto-Regular" size:12.0f]];
NSString *subTitleStr = annotation.subtitle;
[img addSubview:lblPlaceholder1];
[aView addSubview:img];
[img setUserInteractionEnabled:YES];
aView.image = [UIImage imageNamed:#"tracker.png"];//This is marker image view
aView.annotation = annotation;
return aView;
}
Here all the annotations in map are by default visible.
Related
I have a map view in my app that displays the user's location. when the user's location is tapped an image is displayed as below:
is there a way to make this image customized to my liking, so for instance I would like to show the photo that the user has in his own profile, or any other static image that I would like to add.
similar to how the apple maps would show your profile picture in your location dot.
how can I do that here?
here is my code:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
print("user location image tapped")
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true
pinView?.canShowCallout = true
pinView?.isDraggable = true
// pinView?.pinColor = .purple
let rightButton: AnyObject! = UIButton(type: UIButton.ButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
any help on this? thank you.
let imageView = UIImageView(frame: CGRect(0, 0, 25, 25))
imageView.image = UIImage(named: "userpic");
imageView.layer.cornerRadius = imageView.layer.frame.size.width / 2
imageView.layer.masksToBounds = true
anotationView.frame = imageView.frame
I have to set custom image for different pins. With my code I'm able to set custom color for each of them but when I try to set custom image instead of colors, it doesn't work.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(MyAnnotation *)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyAnnotation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.myMap dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
NSString *stringType = [NSString stringWithFormat:#"%#", [(MyAnnotation *)annotationView.annotation stringType]];
if ([stringType isEqualToString:#"0"]) {
annotationView.image = [UIImage imageNamed:#"IconUserCerco.png"];
//annotationView.pinColor = MKPinAnnotationColorGreen;
} else if ([stringType isEqualToString:#"1"]) {
annotationView.image = [UIImage imageNamed:#"IconUserDefault.png"];
//annotationView.pinColor = MKPinAnnotationColorPurple;
} else if ([stringType isEqualToString:#"2"]) {
annotationView.image = [UIImage imageNamed:#"PinUniversity.png"];
//annotationView.pinColor = MKPinAnnotationColorRed;
}
return annotationView;
}
return nil;
}
Any help will be much appreciated. Thanks in advance.
Instead of MKPinAnnotationView can you use MKAnnotationView? You'll have to use following instead of MKPinAnnotationView
MKAnnotationView *annotationView = [self.myMap dequeueReusableAnnotationViewWithIdentifier:identifier];
iOS 9.0 onwards its recommended to use MKAnnotationView. That should solve your problem.
This is what it looks like in iOS 11.x Swift 4, note this won't work if you make the same mistake as me using MKPinAnnotationView. This will make a pin and you won't be able to change the image behind it.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pav:MKAnnotationView?
if (pav == nil)
{
pav = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pav?.isDraggable = true
pav?.canShowCallout = true
pav?.image = UIImage(named: "WIP.png")
pav?.calloutOffset = CGPoint(x: -8, y: 0)
pav?.autoresizesSubviews = true
// pav?.rightCalloutAccessoryView = UIButton(type: .roundedRect)
pav?.leftCalloutAccessoryView = UIButton(type: .contactAdd)
}
else
{
pav?.annotation = annotation;
}
return pav;
}
What should I write in order to put a personal picture instead of the traditional red pin?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annView : MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "currentloc")
annView.pinTintColor = UIColor.redColor()
annView.animatesDrop = true
annView.canShowCallout = true
annView.calloutOffset = CGPointMake(-8, 0)
annView.autoresizesSubviews = true
annView.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
return annView
}
Use MKAnnotationView instead of MKPinAnnotationView, and then set its image property. I'd also suggest implementing the dequeue logic so that annotations can be reused:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annotationIdentifier = "SomeCustomIdentifier" // use something unique that functionally identifies the type of pin
var annotationView: MKAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if annotationView != nil {
annotationView.annotation = annotation
} else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView.image = UIImage(named: "annotation.png")
annotationView.canShowCallout = true
annotationView.calloutOffset = CGPointMake(-8, 0)
annotationView.autoresizesSubviews = true
annotationView.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
}
return annotationView
}
i'm trying to create a MKAnnonationView, but when i tap the annonations they appear with a transparent background. When i press the segmentControllr which shows tableView instead of MKMapView then its white until i tap the annonation again then it become transperent again.
viewdidLoad
pointMapView = MKMapView(frame: CGRectMake(0, 0, self.tableView.frame.width, self.tableView.frame.height))
pointMapView?.showsUserLocation = true
add MKAnnonations
func setGeoPoint(geoPoint:PFGeoPoint, titleString:NSString, imageFile:PFFile, theId:NSString, descString:NSString, dateString:NSString) {
var coordinate = CLLocationCoordinate2DMake(geoPoint.latitude, geoPoint.longitude) as CLLocationCoordinate2D
var pinView:AnnonationClass = AnnonationClass()
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
let theImage = UIImage(data:imageData)
pinView.itemImage = theImage
pinView.setCoordinate(coordinate)
pinView.title = titleString
pinView.subtitle = dateString
self.pointMapView!.addAnnotation(pinView)
}
}
viewForAnnonation
func mapView(mapView: MKMapView!, viewForAnnotation annotation: AnnonationClass!) -> MKAnnotationView! {
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = .Purple
var rightButton: AnyObject! = UIButton.buttonWithType(UIButtonType.DetailDisclosure)
//MapPointAnnotation *point = (MapPointAnnotation*)pinView.annotation;
//rightButton.venue = point.venue;
rightButton.titleForState(UIControlState.Normal)
rightButton.addTarget(self, action: "rightButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
pinView!.rightCalloutAccessoryView = rightButton as UIView
var leftImage: UIImageView = UIImageView(frame: CGRectMake(0, 0, 44, 44))
leftImage.image = annotation.itemImage
pinView!.leftCalloutAccessoryView = leftImage
}
else {
pinView!.annotation = annotation
}
return pinView
}
I want to display an image in my MKMapView instead of little rock pin.
Can someone please put some helpful code here, or tell the way how to do it?
-(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];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:#"pinks.jpg"]; //as suggested by Squatch
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
I am expecting my image pinks.jpg to be on the map, pinning the location instead of default pin view (rock pin shaped). But still I am getting the default image of the pin.
When you want to use your own image for an annotation view, you should create an MKAnnotationView instead of an MKPinAnnotationView.
MKPinAnnotationView is a subclass of MKAnnotationView so it has an image property but it generally overrides that and draws a pin image (that's what it's for).
So change the code to:
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
//pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
//pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:#"pinks.jpg"]; //as suggested by Squatch
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
Notice that animatesDrop is also commented out since that property only exists in MKPinAnnotationView.
If you still want your image annotations to drop, you'll have to do the animation yourself. You can search Stack Overflow for "animatesdrop mkannotationview" and you'll find several answers. Here are the first two:
Is it possible to call animatesDrop in a MKAnnotationView rather than MKPinAnnotationView?
How can I create a custom "pin-drop" animation using MKAnnotationView?
Here's an answer on Swift 3. It dequeues annotation view if possible or creates a new one if not:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !(annotation is MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}
Swift 2.2:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
// Better to make this class property
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier) {
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else {
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
// Configure your annotation view here
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "yourImage")
}
return annotationView
}
I agree with with answer of the Anna and i like to show how will look that in swift3.This answer it's with many other options.Like a resize the image, get a list of images from array and ect.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? PetrolStation {
let identifier = "pinAnnotation"
var view: MKAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
as? MKPinAnnotationView { // 2
dequeuedView.annotation = annotation
view = dequeuedView
} else {
// 3
view = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
//here We put a coordinates where we like to show bubble with text information up on the pin image
view.calloutOffset = CGPoint(x: -7, y: 7)
//Here this is a array of images
let pinImage = PetrolItem[activePlace].imgPetrol?[activePlace]
//Here we set the resize of the image
let size = CGSize(width: 30, height: 30)
UIGraphicsBeginImageContext(size)
pinImage?.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let resizeImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
view.image = resizeImage
//Here we like to put into bubble window a singe for detail Informations
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView
//Here we make change of standard pin image with our image
view.image = resizeImage
}
return view
}
return nil
}