Imagen de color Tinte UIButton

294

Noté que cuando coloco un blanco o negro UIImageen un UISegmentedControlcolor, lo enmascara automáticamente para que coincida con el tono del control segmentado. Pensé que esto era realmente genial, y me preguntaba si podría hacer esto también en otro lugar. Por ejemplo, tengo un montón de botones que tienen una forma uniforme pero colores variados. En lugar de hacer un PNG para cada botón, ¿podría de alguna manera usar esta máscara de color para usar la misma imagen para todos ellos, pero luego establecer un color de tinte o algo para cambiar su color real?

Logan Shire
fuente
¿Puedes publicar la imagen que deseas usar y también la imagen para obtener el resultado deseado?
Pratyusha Terli
esto hace lo mismo desde el
creador

Respuestas:

619

A partir de iOS 7, hay un nuevo método UIImagepara especificar el modo de representación. El uso del modo de representación UIImageRenderingModeAlwaysTemplatepermitirá que el color de la imagen sea controlado por el color de tinte del botón.

C objetivo

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [[UIImage imageNamed:@"image_name"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[button setImage:image forState:UIControlStateNormal]; 
button.tintColor = [UIColor redColor];

Rápido

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red
Ric Santos
fuente
14
Creo que es mejor usar button.imageView.tintColor
M.Othman
3
@ M.Othman solo funciona para mí cuando uso button.tintColor y no button.imageview.tintColor
pnizzle
32
Solo recuerde configurar el modo de representación de imagen en la imagen en xcassets por @hashier
Dean
23
Crear un UIButton de tipo UIButtonTypeSystem respetará automáticamente el tintColor que establezca.
carloshwa 03 de
44
Si tintColorestá demasiado oscuro, asegúrese de adjustsImageWhenHighlightedque NO. (O en IB: "La imagen ajustada resaltada" no está marcada)
Jason Moore
225

Como Ric ya mencionó en su publicación , puede configurar el modo de representación en el código, también puede hacerlo directamente en el catálogo de imágenes, vea la imagen adjunta a continuación. Sólo hay que establecer la Render AsaTemplate Image

ingrese la descripción de la imagen aquí

Advertencia : he tenido problemas con iOS 7 y este enfoque. Entonces, si usa iOS 7 también, es posible que también desee hacerlo en código, como se describe aquí .

más hashier
fuente
1
Como nota al margen, el archivo de imagen debe ser negro y transparente (no blanco y negro)
Axel Guilmin
66
@AxelGuilmin no realmente. Su imagen puede ser del color que desee y transparente. Cualquier color diferente al transparente se convertirá en uno genérico y luego se teñirá con color negro de forma predeterminada.
Alejandro Iván
90

Los botones personalizados aparecen en sus respectivos colores de imagen. Al establecer el tipo de botón en "Sistema" en el guión gráfico (o UIButtonTypeSystemen el código), la imagen del botón tendrá el color de tinte predeterminado.

Tipo de botón El sistema representa los iconos teñidos

(probado en iOS9, Xcode 7.3)

auco
fuente
2
Lo que se puede evitar con los métodos alwaysTemplate y tintColor sugeridos aquí. Con la ventaja del botón .system, obtienes el cambio de color con solo tocar el grifo.
Chris Prince
44

Debe establecer el modo de representación de imagen UIImageRenderingModeAlwaysTemplateen para que tintColorafecte el UIImage. Aquí está la solución en Swift:

let image = UIImage(named: "image-name")
let button = UIButton()
button.setImage(image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: .Normal)
button.tintColor = UIColor.whiteColor()

SWIFT 4x

button.setImage(image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate), for: .normal)
button.tintColor = UIColor.blue
Nick Wargnier
fuente
28

Si tiene un botón personalizado con una imagen de fondo. Puede configurar el color de tinte de su botón y anular la imagen con los siguientes.

En los activos, seleccione el fondo del botón que desea establecer el color de tinte.

En el inspector de atributos de la imagen, configure el valor de representación como "Imagen de plantilla"

ingrese la descripción de la imagen aquí

Ahora, cada vez que configure button.tintColor = UIColor.redsu botón, se mostrará en rojo.

Ilker Baltaci
fuente
si está aquí, puede ir a este enlace: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog y vaya a las imágenes de la plantilla (para servir como explicación)
cspam
Esta es una mejor solución, ya que reduce el código y prácticamente hace lo mismo que la respuesta aceptada.
DS.
Creo que este debería ser el correcto. Menos código y fácil de manejar.
Umair_UAS
17

En Swift puedes hacerlo así:

var exampleImage = UIImage(named: "ExampleImage.png")?.imageWithRenderingMode(.AlwaysTemplate)

Luego, en su punto de vista

exampleButtonOutlet.setImage(exampleImage, forState: UIControlState.Normal)

Y para modificar el color

exampleButtonOutlet.tintColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1) //your color

EDITAR Xcode 8 ya se puede también sólo el modo de representación de la imagen en sus .xcassets a plantilla de la imagen y entonces no necesita declarar específicamente en el var exampleImagemás

henrik-dmg
fuente
14

No estoy seguro de lo que quiere exactamente, pero este método de categoría enmascarará un UIImage con un color específico para que pueda tener una sola imagen y cambiar su color a lo que desee.

ImageUtils.h

- (UIImage *) maskWithColor:(UIColor *)color;

ImageUtils.m

-(UIImage *) maskWithColor:(UIColor *)color 
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width;
    CGFloat height = self.size.height;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);    
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;    
}

Importe la categoría ImageUtils y haga algo como esto ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];
Kirby Todd
fuente
3
Uso kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastenCGBitmapContextCreate
Luis Ascorbe
44
Agradable, pero necesita ser ajustado para los gráficos Retina ... Cuando ejecuto esto en una imagen Retina, me devuelve una no retina.
jowie
Para admitir dispositivos Retina, puede usar la propiedad de escala de la UIDeviceclase: CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;la scalepropiedad existe a partir de iOS 4.0.
Philipp Frischmuth
También debe usar el scalevalor cuando UIImagese crea:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Philipp Frischmuth
8

Swift 4 con customType:

let button = UIButton(frame: aRectHere)
    let buttonImage = UIImage(named: "imageName")
    button.setImage(buttonImage?.withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor = .white
aBikis
fuente
5

Para Xamarin.iOS (C #):

        UIButton messagesButton = new UIButton(UIButtonType.Custom);
        UIImage icon = UIImage.FromBundle("Images/icon.png");
        messagesButton.SetImage(icon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), UIControlState.Normal);
        messagesButton.TintColor = UIColor.White;
        messagesButton.Frame = new RectangleF(0, 0, 25, 25);
Maciej
fuente
5

Swift 3 :

Esta solución podría ser cómoda si ya ha configurado su imagen a través del generador de interfaces xCode. Básicamente tiene una extensión para colorear una imagen:

extension UIImage {
    public func image(withTintColor color: UIColor) -> UIImage{
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let context: CGContext = UIGraphicsGetCurrentContext()!
        context.translateBy(x: 0, y: self.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.setBlendMode(CGBlendMode.normal)
        let rect: CGRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        context.clip(to: rect, mask: self.cgImage!)
        color.setFill()
        context.fill(rect)
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
}

Luego, puede preparar esta extensión UIButton para colorear la imagen para un estado particular:

extension UIButton {
    func imageWith(color:UIColor, for: UIControlState) {
        if let imageForState = self.image(for: state) {
            self.image(for: .normal)?.withRenderingMode(.alwaysTemplate)
            let colorizedImage = imageForState.image(withTintColor: color)
            self.setImage(colorizedImage, for: state)
        }
    }
}

Uso:

myButton.imageWith(.red, for: .normal)

PS (funciona bien también en las celdas de la tabla, no necesita llamar al setNeedDisplay()método, el cambio de color es inmediato debido a la extensión UIImage ..

Alessandro Ornano
fuente
3

Si desea enmascarar manualmente su imagen, aquí hay un código actualizado que funciona con pantallas de retina

- (UIImage *)maskWithColor:(UIColor *)color
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width * self.scale;
    CGFloat height = self.size.height * self.scale;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:self.scale orientation:self.imageOrientation];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;
}
Josh Bernfeld
fuente
2

Deberías intentarlo

Después de configurar el marco

NSArray *arr10 =[NSArray arrayWithObjects:btn1,btn2,nil];
for(UIButton *btn10 in arr10)
{
CAGradientLayer *btnGradient2 = [CAGradientLayer layer];
btnGradient2.frame = btn10.bounds;

btnGradient2.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor colorWithRed:151.0/255.0f green:206.0/255.5 blue:99.0/255.0 alpha:1] CGColor],
                       (id)[[UIColor colorWithRed:126.0/255.0f green:192.0/255.5 blue:65.0/255.0 alpha:1]CGColor],
                       nil];
[btn10.layer insertSublayer:btnGradient2 atIndex:0];

}
guptha
fuente
2

Swift 3.0

    let image = UIImage(named:"NoConnection")!

 warningButton = UIButton(type: .system)        
    warningButton.setImage(image, for: .normal)
    warningButton.tintColor = UIColor.lightText
    warningButton.frame = CGRect(origin: CGPoint(x:-100,y:0), size: CGSize(width: 59, height: 56))

    self.addSubview(warningButton)
Jad
fuente
1

Cambiar la imagen del botón o el color de tinte de la vista de imagen Swift:

btn.imageView?.image = btn.imageView?.image?.withRenderingMode(.alwaysTemplate)

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
Uri Modi
fuente
-1

Nada de lo anterior funcionó para mí, porque el tinte se borró después de hacer clic. Tuve que usar

button.setImageTintColor(Palette.darkGray(), for: UIControlState())
Szymon Klimaszewski
fuente