Farbtönung UIButton Image

294

Ich bemerkte , dass , wenn ich ein weißen oder schwarzen Platz UIImagein eine UISegmentedControlautomatisch Farbmasken es den Farbton der segmentierten Kontrolle anzupassen. Ich fand das wirklich cool und fragte mich, ob ich das auch woanders machen könnte. Zum Beispiel habe ich eine Reihe von Knöpfen, die eine einheitliche Form, aber unterschiedliche Farben haben. Könnte ich, anstatt für jede Schaltfläche ein PNG zu erstellen, diese Farbmaskierung verwenden, um für alle das gleiche Bild zu verwenden, aber dann eine Farbtonfarbe oder etwas anderes festlegen, um ihre tatsächliche Farbe zu ändern?

Logan Shire
quelle
Können Sie das Bild, das Sie verwenden möchten, und das Bild für das gewünschte Ergebnis veröffentlichen?
Pratyusha Terli
Dies tun das gleiche von Interface Builder stackoverflow.com/a/25179217/2051381
Chuy47

Antworten:

619

Ab iOS 7 gibt es eine neue Methode UIImagezum Festlegen des Rendermodus. Wenn Sie den Rendering-Modus verwenden, kann UIImageRenderingModeAlwaysTemplatedie Bildfarbe durch die Farbtonfarbe der Schaltfläche gesteuert werden.

Ziel c

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

Schnell

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red
Ric Santos
quelle
14
Ich denke, es ist besser, button.imageView.tintColor
M.Othman
3
@ M.Othman funktioniert nur für mich, wenn ich button.tintColor und nicht button.imageview.tintColor verwende
pnizzle
32
Denken Sie daran, den Bildrendermodus für das Bild in xcassets per @hashier
Dean
23
Wenn Sie einen UIButton vom Typ UIButtonTypeSystem erstellen, wird die von Ihnen festgelegte tintColor automatisch berücksichtigt.
Carloshwa
4
Wenn Sie tintColorzu dunkel sind, stellen Sie sicher, dass adjustsImageWhenHighlightedNEIN ist. (Oder in IB: "Highlighted Adjusts Image" ist deaktiviert.)
Jason Moore
225

Wie Ric bereits in seinem Beitrag erwähnt hat, können Sie den Rendermodus im Code einstellen. Sie können dies auch direkt im Bildkatalog tun, siehe beigefügtes Bild unten. Stellen Sie einfach das Render AsaufTemplate Image

Geben Sie hier die Bildbeschreibung ein

Vorsichtsmaßnahme Ich hatte Probleme mit iOS 7 und diesem Ansatz. Wenn Sie also auch iOS 7 verwenden, möchten Sie dies möglicherweise auch im Code tun, um sicherzugehen, wie hier beschrieben .

hashier
quelle
1
Als Randnotiz sollte die Bilddatei schwarz und transparent sein (nicht s / w)
Axel Guilmin
6
@ AxelGuilmin nicht wirklich. Ihr Bild kann jede gewünschte Farbe haben und transparent sein. Jede andere Farbe als transparent wird in eine generische Farbe konvertiert und dann standardmäßig mit schwarzer Farbe getönt.
Alejandro Iván
90

Benutzerdefinierte Schaltflächen werden in ihren jeweiligen Bildfarben angezeigt. Wenn Sie den Schaltflächentyp im Storyboard (oder UIButtonTypeSystemim Code) auf "System" setzen , wird das Bild der Schaltfläche mit der Standardfarbe getönt.

Schaltflächentyp System rendert Symbole getönt

(getestet auf iOS9, Xcode 7.3)

auco
quelle
2
Dies kann mit den hier vorgeschlagenen Methoden alwaysTemplate und tintColor vermieden werden. Mit dem Vorteil der .system-Taste erhalten Sie die Farbänderung durch Aufsetzen auf den Wasserhahn.
Chris Prince
44

Sie müssen den Bildwiedergabemodus einzustellen , UIImageRenderingModeAlwaysTemplateum das zu haben , tintColordie UIImage beeinflussen. Hier ist die Lösung in 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
quelle
28

Wenn Sie eine benutzerdefinierte Schaltfläche mit einem Hintergrundbild haben. Sie können die Farbtonfarbe Ihrer Schaltfläche festlegen und das Bild wie folgt überschreiben.

Wählen Sie in Assets den Schaltflächenhintergrund aus, für den Sie die Farbtonfarbe festlegen möchten.

Stellen Sie im Attributinspektor des Bildes den Wert für "Vorlagenbild" ein.

Geben Sie hier die Bildbeschreibung ein

Wenn Sie jetzt Ihre button.tintColor = UIColor.redTaste einstellen, wird sie rot angezeigt.

Ilker Baltaci
quelle
Wenn Sie hier sind, können Sie zu diesem Link gehen: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog und zu Vorlagenbildern gehen (um als Erklärung zu dienen)
cspam
Dies ist eine bessere Lösung, da sie den Code reduziert und fast das Gleiche tut wie die akzeptierte Antwort.
DS.
Ich denke, das sollte der richtige sein. weniger Code und einfach zu handhaben.
Umair_UAS
17

In Swift können Sie das so machen:

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

Dann in Ihrer viewDidLoad

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

Und um die Farbe zu ändern

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

EDIT Xcode 8 Jetzt können Sie auch nur die Rendering - Modus des Bildes in Ihrem .xcassets auf Vorlage Bild und dann brauchen Sie nicht zu erklären , es speziell im var exampleImagemehr

henrik-dmg
quelle
14

Sie wissen nicht genau, was Sie möchten, aber diese Kategoriemethode maskiert ein UIImage mit einer bestimmten Farbe, sodass Sie ein einzelnes Bild haben und seine Farbe nach Belieben ändern können.

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

Importieren Sie die Kategorie ImageUtils und machen Sie so etwas ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];
Kirby Todd
quelle
3
Verwenden Sie kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastaufCGBitmapContextCreate
Luis Ascorbe
4
Schön, muss aber für Retina-Grafiken optimiert werden ... Wenn ich dies auf einem Retina-Bild ausführe, erhalte ich ein Nicht-Retina-Bild.
Jowie
Zur Unterstützung von Retina-Geräten können Sie die Eigenschaft scale der UIDeviceKlasse verwenden: CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;Die scaleEigenschaft ist ab iOS 4.0 vorhanden.
Philipp Frischmuth
Sie müssen auch den scaleWert verwenden, wenn der UIImageerstellt wird:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Philipp Frischmuth
8

Swift 4 mit customType:

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

Für 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
quelle
5

Swift 3 :

Diese Lösung kann bequem sein, wenn Sie Ihr Image bereits über den xCode Interface Builder festgelegt haben. Grundsätzlich haben Sie eine Erweiterung, um ein Bild einzufärben:

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

Anschließend können Sie diese UIButton- Erweiterung vorbereiten , um das Bild für einen bestimmten Status einzufärben :

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

Verwendungszweck:

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

PS (funktioniert auch in Tabellenzellen gut, Sie müssen die setNeedDisplay()Methode nicht aufrufen , die Änderung der Farbe erfolgt sofort aufgrund der UIImage- Erweiterung.

Alessandro Ornano
quelle
3

Wenn Sie Ihr Bild manuell maskieren möchten, finden Sie hier aktualisierten Code, der mit Retina-Bildschirmen funktioniert

- (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
quelle
2

Du solltest es versuchen

Nach dem Einstellen des Rahmens

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
quelle
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
quelle
1

Ändern Sie das Farbtonbild oder die Farbfarbe der Bildansicht. Schnell:

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

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

Keiner der oben genannten Punkte hat bei mir funktioniert, da der Farbton nach dem Klicken gelöscht wurde. Ich musste benutzen

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