Odcień koloru UIButton Obraz

294

Zauważyłem, że kiedy umieścić biały lub czarny UIImagedo UISegmentedControlniej automatycznie kolorowych masek to, aby dopasować odcień kontroli segmentowej. Myślałem, że to naprawdę fajne i zastanawiałem się, czy mógłbym to zrobić również gdzie indziej. Na przykład mam kilka przycisków, które mają jednolity kształt, ale różne kolory. Zamiast tworzyć PNG dla każdego przycisku, czy mógłbym w jakiś sposób użyć tego maskowania kolorów, aby użyć tego samego obrazu dla wszystkich z nich, ale następnie ustawić kolor odcienia lub coś, aby zmienić ich rzeczywisty kolor?

Logan Shire
źródło
Czy możesz opublikować obraz, którego chcesz użyć, a także obraz dla pożądanego rezultatu?
Pratyusha Terli
zrób to samo z konstruktorem interfejsów stackoverflow.com/a/25179217/2051381
Chuy47

Odpowiedzi:

619

Począwszy od systemu iOS 7, dostępna jest nowa metoda UIImageokreślania trybu renderowania. Użycie trybu renderowania UIImageRenderingModeAlwaysTemplatepozwoli kontrolować kolor obrazu za pomocą koloru odcienia przycisku.

Cel C

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

Szybki

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red
Ric Santos
źródło
14
Myślę, że lepiej jest użyć
button.imageView.tintColor
3
@ M.Othman działa tylko dla mnie, gdy używam button.tintColor, a nie
button.imageview.tintColor
32
Pamiętaj tylko, aby ustawić tryb renderowania obrazu na obrazie w xcassets na @hashier
Dean
23
Utworzenie UIButton typu UIButtonTypeSystem automatycznie zaakceptuje ustawiony kolor tintColor.
carloshwa,
4
Jeśli twoje tintColorjest zbyt ciemne, upewnij się, że adjustsImageWhenHighlightedNIE. (Lub w IB: „Wyróżnione dopasowania obrazu” nie są zaznaczone.)
Jason Moore,
225

Jak Ric wspomniał już w swoim poście , możesz ustawić tryb renderowania w kodzie, możesz to również zrobić bezpośrednio w katalogu obrazów, patrz załączony obraz poniżej. Wystarczy ustawić Render AsnaTemplate Image

wprowadź opis zdjęcia tutaj

Zastrzeżenie Mam problemy z iOS 7 i tym podejściem. Więc jeśli używasz iOS 7, możesz to zrobić również w kodzie, aby się upewnić, jak opisano tutaj .

hashier
źródło
1
Na marginesie, plik obrazu powinien być czarny i przezroczysty (nie czarno-biały)
Axel Guilmin
6
@AxelGuilmin nie bardzo. Twój obraz może być dowolnego koloru i przezroczysty. Każdy kolor inny niż przezroczysty zostanie przekonwertowany na ogólny, a następnie będzie domyślnie zabarwiony kolorem czarnym.
Alejandro Iván
90

Przyciski niestandardowe pojawiają się w odpowiednich kolorach obrazu. Ustawienie typu przycisku na „System” w serii ujęć (lub UIButtonTypeSystemw kodzie) spowoduje wyświetlenie obrazu przycisku z domyślnym kolorem odcienia.

Typ przycisku System renderuje ikony Przyciemniane

(testowany na iOS9, Xcode 7.3)

auco
źródło
2
Tego można uniknąć za pomocą sugerowanych tutaj metod alwaysTemplate i tintColor. Zaletą przycisku .system jest zmiana koloru po dotknięciu kranu.
Chris Prince
44

Musisz ustawić tryb renderowania obrazu na UIImageRenderingModeAlwaysTemplate, aby mieć tintColorwpływ na UIImage. Oto rozwiązanie w 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
źródło
28

Jeśli masz przycisk niestandardowy z obrazem w tle. Możesz ustawić kolor odcienia swojego przycisku i zastąpić obraz następującymi.

W zasobach wybierz tło przycisku, dla którego chcesz ustawić kolor odcienia.

W inspektorze atrybutów obrazu ustaw wartość renderowania jako „Obraz szablonu”

wprowadź opis zdjęcia tutaj

Teraz po każdym ustawieniu button.tintColor = UIColor.redprzycisk będzie wyświetlany na czerwono.

Ilker Baltaci
źródło
jeśli jesteś tutaj, możesz przejść do tego linku: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog i zejdź do obrazów szablonów (aby służyć jako wyjaśnienie)
cspam
Jest to lepsze rozwiązanie, ponieważ redukuje kod i prawie robi to samo, co zaakceptowana odpowiedź.
DS.
Myślę, że to powinno być właściwe. mniej kodu i łatwy w obsłudze.
Umair_UAS
17

W Swift możesz to zrobić w następujący sposób:

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

Następnie w twoim widokuDidLoad

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

I aby zmodyfikować kolor

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

EDYCJA Xcode 8 Teraz możesz także po prostu tryb renderowania obrazu z zestawu .xcassets do obrazu szablonu i nie musisz var exampleImagejuż go deklarować

henrik-dmg
źródło
14

Nie jestem pewien, czego dokładnie chcesz, ale ta metoda kategorii zamaskuje obraz UIIm określonego koloru, abyś mógł mieć pojedynczy obraz i zmienić jego kolor na dowolny.

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

Zaimportuj kategorię ImageUtils i zrób coś takiego ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];
Kirby Todd
źródło
3
Użyj kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastnaCGBitmapContextCreate
Luis Ascorbe
4
Fajnie, ale trzeba poprawić grafikę Retina ... Kiedy uruchomię to na obrazie Retina, zwraca mi obraz inny niż Retina.
jowie
W celu wspierania urządzeń siatkówce można użyć właściwości skali UIDeviceklasy: właściwość istnieje w iOS 4.0. CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;scale
Philipp Frischmuth,
Musisz także użyć tej scalewartości, gdy UIImagezostanie utworzona:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Philipp Frischmuth,
8

Swift 4 with customType:

let button = UIButton(frame: aRectHere)
    let buttonImage = UIImage(named: "imageName")
    button.setImage(buttonImage?.withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor = .white
aBikis
źródło
5

W przypadku 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
źródło
5

Swift 3 :

To rozwiązanie może być wygodne, jeśli ustawiłeś już obraz za pomocą konstruktora interfejsu xCode. Zasadniczo masz jedno rozszerzenie do pokolorowania obrazu:

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

Następnie możesz przygotować to rozszerzenie UIButton, aby pokolorować obraz dla określonego stanu:

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

Stosowanie:

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

PS (działa dobrze również w komórkach tabeli, nie trzeba wywoływać setNeedDisplay()metody, zmiana koloru jest natychmiastowa z powodu rozszerzenia UIImage) .

Alessandro Ornano
źródło
3

Jeśli chcesz ręcznie maskować obraz, oto zaktualizowany kod, który działa z ekranami siatkówki

- (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
źródło
2

Powinieneś spróbować

Po ustawieniu ramki

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

}
gupta
źródło
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
źródło
1

Zmień kolor przycisku lub kolor odcienia widoku obrazu Szybki:

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

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
Urvish Modi
źródło
-1

Żadne z powyższych nie działało dla mnie, ponieważ odcień został wyczyszczony po kliknięciu. Musiałem użyć

button.setImageTintColor(Palette.darkGray(), for: UIControlState())
Szymon Klimaszewski
źródło