Reputation: 13860
I'm writing an application for iOS 7.0+
and I wanted to use new feature witch is: imageWithRenderingMode
. I have a map annotation with this code:
-(MKAnnotationView*)annotationView {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:self reuseIdentifier:@"AnnotationIdentifier"];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [[UIImage imageNamed:@"star"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.tintColor = [UIColor redColor];
return annotationView;
}
I was expected that my pins will be red, but stays black, only the callout (i) icon turns red.
I was trying to set self.view.tintColor
and self.mapView.tintColor
in my ViewController
but this not working either. How to turns this pins red?
Upvotes: 17
Views: 6790
Reputation: 331
this works for me:
extension MKAnnotationView {
public func set(image: UIImage, with color : UIColor) {
let view = UIImageView(image: image.withRenderingMode(.alwaysTemplate))
view.tintColor = color
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
guard let graphicsContext = UIGraphicsGetCurrentContext() else { return }
view.layer.render(in: graphicsContext)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.image = image
}
}
(based on @Marcio Fonseca's answer)
edit: here's a small tweak to have both full color and tinted images:
extension MKAnnotationView {
public func setPin(image: UIImage = UIImage(systemName: "mappin.circle.fill")!,
with color : UIColor? = nil) {
let view: UIImageView
if let color = color {
// set tint color if specified
view = UIImageView(image: image.withRenderingMode(.alwaysTemplate))
view.tintColor = color
} else {
// keep original image colors if unspecified
view = UIImageView(image: image)
}
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
guard let graphicsContext = UIGraphicsGetCurrentContext() else { return }
view.layer.render(in: graphicsContext)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.image = image
}
}
here's how to call it:
// Use fallback pin image ("mappin.circle.fill") without tint
view.setPin()
// note: this will set it to black.
// you could change the default UIColor? value to .systemRed and pass nil in
// the rare case you might need to use an untinted app asset image
// Use fallback pin image with tint
view.setPin(with: .systemYellow)
// App assets image without tint
view.setPin(image: UIImage(named: "estech")!)
// App assets image with tint
view.setPin(image: UIImage(named: "estech")!, with: .systemBlue)
Upvotes: 4
Reputation: 3789
Realize I'm very late to the game, however I was looking for the same thing as you, but found this useful.
Use MKMarkerAnnotationView
, which has an attribute markerTintColor
.
You won't get a custom pin image, but it will look a lot like the marker you had in your questions (see my attached image).
Here's a snippet of how I use it:
// Somewhere else
mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMarkerAnnotationView.self.description())
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let companyAnnotation = annotation as? CompanyAnnotation else { return nil }
let view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: MKMarkerAnnotationView.self.description())
view.markerTintColor = .colorFor(category: companyAnnotation.company.category)
return view
}
Upvotes: 4
Reputation: 719
Same as @sandy-chapman but in Swift 3. My images got flipped so I flip them back again.
extension UIImage {
func colorized(color : UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
if let context = UIGraphicsGetCurrentContext() {
context.setBlendMode(.multiply)
context.translateBy(x: 0, y: self.size.height)
context.scaleBy(x: 1.0, y: -1.0)
context.draw(self.cgImage!, in: rect)
context.clip(to: rect, mask: self.cgImage!)
context.setFillColor(color.cgColor)
context.fill(rect)
}
let colorizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return colorizedImage!
}
}
Upvotes: 5
Reputation: 22252
How frustrating. I solved it like this (sans the other property configurations):
-(MKAnnotationView*)annotationView {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation: self reuseIdentifier: @"AnnotationIdentifier"];
UIImage *image = [[UIImage imageNamed: @"star"] imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate];
UIImageView *screwYouApple = [[UIImageView alloc] initWithImage: image];
screwYouApple.tintColor = [UIColor redColor];
[annotationView addSubview: screwYouApple];
return annotationView;
}
Basically, I blow off the image
property of the annotationView
and use a properly tinted UIImageView
as a subview
of the annotation.
Variable naming helped the experience be cathartic.
Upvotes: 4
Reputation: 11341
There's a better solution than those proposed that doesn't involve creating a UIImageView
.
This Swift code will create a colored version of your UIImage
.
extension UIImage {
func colorized(color : UIColor) -> UIImage {
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0);
let context = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(context, .Multiply)
CGContextDrawImage(context, rect, self.CGImage)
CGContextClipToMask(context, rect, self.CGImage)
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let colorizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return colorizedImage
}
}
Call it like this:
UIImage(named: "myImage")!
.imageWithRenderingMode(.AlwaysTemplate)
.colorized(UIColor.red())
Upvotes: 12
Reputation: 489
I could make this work by capturing an UIView to UIImage:
UIImage *pin = [UIImage imageNamed:@"pin"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, pin.size.width, pin.size.height)];
imageView.image = [pin imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.tintColor = [UIColor grayColor]; // set the desired color
// now the magic...
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, imageView.opaque, 0.0);
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
annotationView.image = img;
Upvotes: 6
Reputation: 23624
It does not appear that you are able to accomplish this at all using tintColor
. MKAnnotationView
does not use the tint color for image rendering like a UIImageView
does. You'll need to either write some sort of method to draw a correctly colored image yourself, or provide an image with the color you want.
Upvotes: 2