Używanie koloru Tint w UIImageView

118

Mam własną podklasę UIButton. Dodaję UIImageViewna to i dodaję obrazek. Chciałbym pomalować obraz kolorem tinta, ale to nie działa.

Jak dotąd mam:

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

i przy wyborze:

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

Co zrobiłem źle? (Kolor obrazu zawsze pozostaje taki sam, jak pierwotnie).

Marko Zadravec
źródło
czy jesteś w stanie setTintColorpodczas tworzenia iconView ?
Himanshu Joshi
1
masz na myśli po self.iconView = [UIImageView assign] ...? Tak, mogę, ale to nie działa.
Marko Zadravec
Następnie użyj CGContext. Być może znajdziesz swoją odpowiedź tutaj stackoverflow.com/a/19275079/1790571
Himanshu Joshi
Tak, widzę ten post, ale naprawdę nie rozumiem, dlaczego mój kod nie działa. Używanie koloru tinta to znacznie czystsza ścieżka.
Marko Zadravec

Odpowiedzi:

237

Zamiast tego kodu:

[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

powinieneś mieć:

image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Użyj tego w Swift 4.1

image = UIImage(named: "name")!.withRenderingMode(.alwaysTemplate)
Marko Zadravec
źródło
9
Nie głupi błąd, ale bardzo ważny szczegół. Dzięki za opublikowanie tego. Właśnie zaoszczędziłeś mi dużo czasu. (poprawiona literówka)
Alex Zavatone
47
Możesz wybrać obraz w zasobach i wybrać domyślny tryb renderowania w prawym panelu
Nikolay Shubenkov
Doskonały! Ale jak powrócić do oryginalnego, nie przyciemnionego obrazu?
Marsman,
Jeśli chcesz uzyskać niezabarwiony obraz, możesz: zapisać przyciemniony obraz w innej zmiennej: UIImage image2 = [image imageWithR ....] lub możesz ponownie załadować obraz z pliku: image = [UIImage imageNamed: @ "more" ];
Marko Zadravec,
89

Możesz również ustawić to w swoim zasobie. Upewnij się, że obraz zawiera wszystkie białe piksele + przezroczyste. wprowadź opis obrazu tutaj

StackUnderflow
źródło
6
Zrobiłem to wszystko, ale z jakiegoś powodu tintColor u mnie nie działa. Masz jakiś pomysł, czego jeszcze mógłbym spróbować?
Banan
1
Jakiego formatu obrazu używasz? Czy obraz jest cały biały + alfa?
StackUnderflow
3
Co dziwne, podczas moich pierwszych kilku serii tylko 2/3 obrazów odebrało kolor. Po wyczyszczeniu i zbudowaniu wszystkich obrazów podniosłem odcień.
MathewS,
Może mógłbyś zgłosić to Apple?
StackUnderflow
11
@Banana, jest to znany problem polegający na tym, że obrazy nie używają odcienia. Jakiś czas temu zgłosiłem to firmie Apple, a oni oznaczyli to jako duplikat, więc na pewno o tym wiedzą. Obejście problemu polega na tym, aby nie ustawiać UIImageView na obraz w Storyboard. Po prostu miej pusty UIImageView, a następnie ustaw go w viewDidLoad (lub w innym miejscu), a zobaczysz tintColor na obrazie.
Mark Moeykens
38

(Nie można edytować postu @Zhaolong Zhong)

W Swift 3.0 możesz:

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

yourImageView.image = image

yourImageView.tintColor = UIColor.blue
odemolliens
źródło
19

W Swift 2.0+ możesz:

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

yourImageView.image = image

yourImageView.tintColor = UIColor.blueColor()
Zhaolong Zhong
źródło
11

Szybka wersja: 5.2.0

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

Cel C

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

Lub

Możesz również ustawić to w swoim zasobie.

wprowadź opis obrazu tutaj

Nischal Hada
źródło
7

Jeden krok dalej. To jest podklasa typu drop-in UIImageView. (Nie jest to dokładne rozwiązanie dla oryginalnego pytania). Użyj w programie Interface Builder, ustawiając nazwę klasy na TintedImageView. Aktualizacje w czasie rzeczywistym wewnątrz projektanta wraz ze zmianą koloru odcienia.

(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
źródło
2
nie działa, ale zmienia func configure na: self.image = self.image? .withRenderingMode (UIImageRenderingMode.alwaysTemplate) let color = super.tintColor super.tintColor = UIColor.clear super.tintColor = color
lolo_house
5

Utwórz plik imageView

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

Zrób obraz

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

Połącz je razem

    imageView?.image = image

Pokaż to

view.addSubview(imageView)
Gary Davies
źródło
1

wszystko powiedziane jest poprawne. mój wkład Jeśli nie możesz / nie chcesz zastosować do każdego UiImageView LUB ze względu na wydajność musisz renderować RAZ (lub przykład dla komórek widoków tabel)

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
    }

I ustaw wszystkie elementy UI w tym UIImage.

ingconti
źródło
1

Odpowiedź @odemolliens powinna po prostu działać.

Ale jeśli nadal masz problemy, upewnij się, że kolor tinty, który stosujesz do UIImageView, różni się od zdefiniowanego w Interface Builder.

rockdaswift
źródło