Imagem de UIButton de tonalidade de cor


294

Percebi que quando coloco um branco ou preto UIImageem uma UISegmentedControlcor, ela automaticamente a mascara para corresponder à tonalidade do controle segmentado. Eu pensei que isso era muito legal, e queria saber se eu poderia fazer isso em outro lugar também. Por exemplo, eu tenho vários botões que têm uma forma uniforme, mas cores variadas. Em vez de criar um PNG para cada botão, eu poderia, de alguma forma, usar essa máscara de cores para usar a mesma imagem em todos eles, mas depois definir uma cor de tonalidade ou algo para alterar a cor real?


Você pode postar a imagem que deseja usar e também a imagem para o resultado desejado?
Pratyusha Terli

Isso faz o mesmo do criador de interface stackoverflow.com/a/25179217/2051381 #
0000 Chuy47

Respostas:


619

No iOS 7, existe um novo método UIImagepara especificar o modo de renderização. O uso do modo de renderização UIImageRenderingModeAlwaysTemplatepermitirá que a cor da imagem seja controlada pela cor da tonalidade do botão.

Objetivo-C

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

14
Eu acho que é melhor usar o
button.imageView.tintColor

3
@ M.Othman só funciona para mim quando eu uso button.tintColor e não button.imageview.tintColor
pnizzle

32
Basta lembrar a imagem Jogo do modo de renderização na imagem em xcassets por @hashier
Dean

23
Criar um UIButton do tipo UIButtonTypeSystem respeitará automaticamente o tintColor que você definir.
precisa saber é o seguinte

4
Se o seu tintColorestiver muito escuro, verifique se adjustsImageWhenHighlightedNÃO. (Ou em IB: "Destaque ajusta a imagem" está desmarcada.)
Jason Moore

225

Como Ric já mencionou em seu post, você pode definir o modo de renderização no código, também pode fazer isso diretamente no catálogo de imagens, veja a imagem anexada abaixo. Basta definir o Render AsqueTemplate Image

insira a descrição da imagem aqui

Advertência Eu tive problemas com o iOS 7 e essa abordagem. Portanto, se você também usa o iOS 7, pode fazê-lo em código, para ter certeza, conforme descrito aqui .


1
Como uma nota lateral, o arquivo de imagem deve ser preto e transparente (não b & w)
Axel Guilmin

6
@AxelGuilmin não é verdade. Sua imagem pode ter qualquer cor desejada e transparente. Qualquer cor diferente de transparente será convertida em genérica e, em seguida, será pintada com a cor preta por padrão.
Alejandro Iván

90

Os botões personalizados aparecem em suas respectivas cores de imagem. Definir o tipo de botão como "Sistema" no storyboard (ou UIButtonTypeSystemno código) renderizará a imagem do botão com a cor padrão da tonalidade.

Tipo de botão Sistema renderiza ícones coloridos

(testado no iOS9, Xcode 7.3)


2
O que pode ser evitado com os métodos alwaysTemplate e tintColor sugeridos aqui. Com a vantagem do botão .system, você obtém a mudança de cor com o toque na torneira.
Chris Prince

44

Você deve definir o modo de renderização da imagem UIImageRenderingModeAlwaysTemplatepara tintColorafetar a UIImage. Aqui está a solução no 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

28

Se você tiver um botão personalizado com uma imagem de plano de fundo. Você pode definir a cor da tonalidade do seu botão e substituir a imagem pelas seguintes.

Nos ativos, selecione o plano de fundo do botão que você deseja definir na cor da tonalidade.

No inspetor de atributos da imagem, defina o valor renderizado como "Imagem do modelo"

insira a descrição da imagem aqui

Agora, sempre que você definir button.tintColor = UIColor.redo botão, será exibido em vermelho.


se você estiver aqui, acesse este link: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog e vá até as imagens dos modelos (para servir de explicação)
cspam

Essa é uma solução melhor, pois reduz o código e praticamente faz a mesma coisa que a resposta aceita.
DS.

Eu acho que esse deve ser o correto. menos código e fácil de manusear.
Umair_UAS

17

No Swift, você pode fazer o seguinte:

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

Então, na sua viewDidLoad

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

E para modificar a cor

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

EDIT Xcode 8 Agora você também pode apenas o modo de renderização da imagem em seus .xcassets para Template Image e, em seguida, não precisa declará-la especificamente var exampleImagemais


14

Não sabe exatamente o que deseja, mas esse método de categoria mascara uma UIImage com uma cor especificada, para que você possa ter uma única imagem e alterá-la para o que quiser.

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 a categoria ImageUtils e faça algo assim ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];

3
Use kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastonCGBitmapContextCreate
Luis Ascorbe

4
Bom, mas precisa ser ajustado para os gráficos Retina ... Quando executo isso em uma imagem Retina, ela retorna uma que não é retina.
jowie

Para oferecer suporte a dispositivos Retina, você pode usar a propriedade scale da UIDeviceclasse: CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;A scalepropriedade existe no iOS 4.0.
Philipp Frischmuth

Você também precisa usar o scalevalor quando ele UIImageé criado:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Philipp Frischmuth

8

Swift 4 com customType:

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

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);

5

Swift 3 :

Essa solução pode ser confortável se você já configurou sua imagem através do construtor de interface xCode. Basicamente, você tem uma extensão para colorir uma imagem:

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
    }
}

Em seguida, você pode preparar esta extensão UIButton para colorir a imagem para um estado específico:

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 (funcionando bem também nas células da tabela, você não precisa chamar o setNeedDisplay()método, a alteração da cor é imediata devido à extensão UIImage .


3

Se você deseja mascarar manualmente sua imagem, aqui está um código atualizado que funciona com telas 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;
}

2

Você deveria tentar

Depois de definir o quadro

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];

}

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)

1

Alterar a imagem do botão ou a cor da tonalidade da visualização da imagem Swift:

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

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

-1

Nenhuma das opções acima funcionou para mim, porque a tonalidade foi limpa após o clique. Eu tive que usar

button.setImageTintColor(Palette.darkGray(), for: UIControlState())
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.