Uso de Tint color en UIImageView

118

Tengo mi propia subclase de UIButton . Lo agrego UIImageViewy agrego una imagen. Me gustaría pintarlo sobre la imagen con un color de tinte pero no funciona.

Hasta ahora tengo:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        self.backgroundColor = [UIColor clearColor];
        self.clipsToBounds = YES;

        self.circleView = [[UIView alloc]init];
        self.circleView.backgroundColor = [UIColor whiteColor];
        self.circleView.layer.borderColor = [[Color getGraySeparatorColor]CGColor];
        self.circleView.layer.borderWidth = 1;
        self.circleView.userInteractionEnabled = NO;
        self.circleView.translatesAutoresizingMaskIntoConstraints = NO;
        [self addSubview:self.circleView];

        self.iconView = [[UIImageView alloc]init];
        [self.iconView setContentMode:UIViewContentModeScaleAspectFit];
        UIImage * image = [UIImage imageNamed:@"more"];
        [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        self.iconView.image = image;
        self.iconView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.circleView addSubview:self.iconView];
        ...

y en la selección:

- (void) setSelected:(BOOL)selected
{
    if (selected) {
        [self.iconView setTintColor:[UIColor redColor]];
        [self.circleView setTintColor:[UIColor redColor]];
    }
    else{
        [self.iconView setTintColor:[UIColor blueColor]];
        [self.circleView setTintColor:[UIColor blueColor]];
    }  
}

¿Qué hice mal? (El color de la imagen siempre es el mismo que era originalmente).

Marko Zadravec
fuente
¿Puedes hacerlo setTintColorcuando estás creando el iconView ?
Himanshu Joshi
1
¿Quieres decir después de self.iconView = [UIImageView alloc] ...? Sí, puedo, pero no funciona.
Marko Zadravec
Entonces use CGContext. Puede ser que pueda encontrar su respuesta aquí stackoverflow.com/a/19275079/1790571
Himanshu Joshi
Sí, veo esta publicación, pero realmente no entiendo por qué mi código no funciona. El uso de tinte de color es un camino mucho más limpio.
Marko Zadravec

Respuestas:

237

En lugar de este código:

[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Deberías:

image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Use esto en Swift 4.1

image = UIImage(named: "name")!.withRenderingMode(.alwaysTemplate)
Marko Zadravec
fuente
9
No es un error estúpido, sino un detalle muy importante. Gracias por publicar esto. Me ahorraste mucho tiempo. (error tipográfico corregido)
Alex Zavatone
47
Puede seleccionar la imagen en los activos y seleccionar en el modo de renderizado predeterminado del panel derecho
Nikolay Shubenkov
¡Excelente! Pero, ¿cómo volver a la imagen original sin teñir?
Marsman
Si desea obtener una imagen sin teñir, puede: almacenar una imagen teñida en una variable diferente: UIImage image2 = [image imageWithR ....], o puede volver a cargar la imagen desde el archivo: image = [UIImage imageNamed: @ "más" ];
Marko Zadravec
89

También puede configurar esto en su activo. Asegúrese de que su imagen contenga todos los píxeles blancos + transparentes. ingrese la descripción de la imagen aquí

StackUnderflow
fuente
6
Hice todo esto, pero por alguna razón el tintColor no me funciona. ¿Alguna idea de qué más podría intentar?
Banana
1
¿Qué tipo de formato de imagen estás usando? ¿Y la imagen es todo blanco + alfa?
StackUnderflow
3
Extrañamente, en mi primer par de ejecuciones, solo 2/3 imágenes recogieron el color del tinte. Después de limpiar y construir todas las imágenes recogieron el tinte.
MathewS
¿Quizás podrías informar eso a Apple?
StackUnderflow
11
@Banana, este es un problema conocido de las imágenes que no usan el color del tinte. Se lo había informado a Apple hace un tiempo y lo marcaron como un duplicado, por lo que definitivamente lo saben. La solución es no configurar su UIImageView en una imagen en el Storyboard. Así que solo tenga un UIImageView en blanco y luego configúrelo en viewDidLoad (o en otro lugar) y luego verá el tintColor en la imagen.
Mark Moeykens
38

(No se puede editar la publicación de @Zhaolong Zhong)

En swift 3.0 , puede hacer:

let image = UIImage(named: "your_image_name")!.withRenderingMode(.alwaysTemplate)

yourImageView.image = image

yourImageView.tintColor = UIColor.blue
odemolliens
fuente
19

En swift 2.0+, puede hacer:

let image = UIImage(named: "your_image_name")!.imageWithRenderingMode(.AlwaysTemplate)

yourImageView.image = image

yourImageView.tintColor = UIColor.blueColor()
Zhaolong Zhong
fuente
11

Versión Swift: 5.2

let tintableImage = UIImage(named: "myImage")?.withRenderingMode(.alwaysTemplate)
imageView.image = tintableImage
imageView.tintColor = UIColor.red

C objetivo

self.imgView.image = [self.imgView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[self.imgView setTintColor:[UIColor darkGrayColor]];

O

También puede configurar esto en su activo.

ingrese la descripción de la imagen aquí

Nischal Hada
fuente
7

Un paso mas alla. Esta es una subclase de UIImageView. (No es una solución exacta para la pregunta original). Úselo en Interface Builder configurando el nombre de la clase en TintedImageView. Se actualiza en tiempo real dentro del diseñador a medida que cambia el color del tinte.

(Swift 3.1, Xcode 8.3)

import UIKit

@IBDesignable class TintedImageView: UIImageView {
    override func prepareForInterfaceBuilder() {
        self.configure()
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        self.configure()
    }

    @IBInspectable override var tintColor: UIColor! {
        didSet {
            self.configure()
        }
    }

    private func configure() {
        self.image = self.image?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
    }
}
Daniel
fuente
2
no funciona, pero modifica la configuración de la función a: self.image = self.image? .withRenderingMode (UIImageRenderingMode.alwaysTemplate) let color = super.tintColor super.tintColor = UIColor.clear super.tintColor = color
lolo_house
5

Hacer el imageView

    let imageView = UIImageView(frame: frame!)
    imageView.contentMode = .ScaleAspectFit
    imageView.tintColor = tintColor

Haz la imagen

    let mainBundle = NSBundle.mainBundle()
    var image = UIImage(named: filename!, inBundle: mainBundle, compatibleWithTraitCollection: nil)
    image = image?.imageWithRenderingMode(.AlwaysTemplate)

Conectarlos juntos

    imageView?.image = image

Mostrarlo

view.addSubview(imageView)
Gary Davies
fuente
1

todo lo dicho es correcto. mi contribución Si no puede / no quiere aplicar a cada UiImageView, O para mayor eficiencia, necesita renderizar UNA VEZ (o ejemplo para celdas de vistas de tabla)

func tint(with color: UIColor) -> UIImage {
        var image = withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        color.set()

        image.draw(in: CGRect(origin: .zero, size: size))
        image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }

Y establezca todos los elementos de la interfaz de usuario en este UIImage.

ingconti
fuente
1

La respuesta de @odemolliens debería funcionar.

Pero si aún tiene problemas, asegúrese de que el color de tinte que está aplicando a UIImageView sea diferente al definido en Interface Builder.

rockdaswift
fuente