Zmodyfikuj UIImage renderingMode z pliku storyboard / xib


95

Czy można zmodyfikować UIImagea renderingModez edytora scenorysu lub XIB?

Celem jest zastosowanie tintColorsię do konkretnego UIImageViewobiektu.

Odpowiedzi:


101

Oto, jak możesz to zrobić w plikach .xib lub scenorysach:

(Obj-C) Utwórz kategorię na UIImageView:

@interface UIImageView (Utils)

- (void)setImageRenderingMode:(UIImageRenderingMode)renderMode;

@end

@implementation UIImageView (Utils)

- (void)setImageRenderingMode:(UIImageRenderingMode)renderMode
{
    NSAssert(self.image, @"Image must be set before setting rendering mode");
    self.image = [self.image imageWithRenderingMode:renderMode];
}

@end

(Swift 4) Utwórz rozszerzenie dla UIImageView:

extension UIImageView {
    func setImageRenderingMode(_ renderMode: UIImage.RenderingMode) {
        assert(image != nil, "Image must be set before setting rendering mode")
        // AlwaysOriginal as an example
        image = image?.withRenderingMode(.alwaysOriginal)
    }
}

Następnie w Inspektorze tożsamości w pliku xib dodaj atrybut środowiska uruchomieniowego:

wprowadź opis obrazu tutaj


44
Uwielbiam tę odpowiedź, że jest odpowiedzią na pytanie.
glony

1
Wolałbym raczej utworzyć podklasę UIImageView, aby ustawić wartość klucza. Ponieważ jest to łatwiejsze do skonfigurowania i możemy uniknąć ustawienia liczby w wartości wyliczenia. Na przykład: `@implementation TemplateRenderingImageView - (id) initWithCoder: (NSCoder *) aDecoder {self = [super initWithCoder: aDecoder]; if (self) {self.image = [self.image imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]; } powrót siebie; } @ end`
john fantasy,

1
Świetna odpowiedź! Zrzuty ekranu były pomocne.
BigSauce,

1
Oczywiście nie działa z Launch Screen.xib, ponieważ nie można z nim używać atrybutów środowiska wykonawczego zdefiniowanych przez użytkownika.
Steve Moser

3
Kodowanie 2 jako wartość jest złe, złe, złe .. Użycie katalogu xcassets jest właściwą odpowiedzią.
tGilani,

198

Możesz ustawić tryb renderowania obrazu nie w .xibpliku, ale w .xcassetsbibliotece.

Po dodaniu obrazu do biblioteki zasobów, wybierz obraz i otwórz inspektor atrybutów po prawej stronie Xcode. Znajdź atrybut „Renderuj jako” i ustaw go na „szablon”.

Po ustawieniu trybu renderowania obrazu, możesz dodać kolor tinty do pliku UIImageViewa .xiblub .storyboard, aby dostosować kolor obrazu.

To ustawia właściwość na obrazie, gdziekolwiek jest używany, a nie tylko w jednym pliku konstruktora interfejsu, ale w prawie wszystkich przypadkach (z którymi się spotkałem) jest to zachowanie, które chcesz.

Zrzut ekranu programu Xcode pokazujący inspektora atrybutów obrazu

Kilka uwag:

  • Wygląda na to, że kolor obrazu nie zmienił się w narzędziu do tworzenia interfejsu (od Xcode 6.1.1), ale będzie działał po uruchomieniu aplikacji.
  • Doświadczyłem pewnych błędów związanych z tą funkcją, aw niektórych sytuacjach musiałem usunąć i ponownie dodać plik UIImageView. Nie zagłębiałem się w to głęboko.
  • Działa to również świetnie w przypadku innych UIKitComponentsobrazów, takich jak obrazy z plików UIButton„i UIBarButtonItem”.
  • Jeśli masz kilka białych obrazów, które są niewidoczne w bibliotece zasobów, uczynienie ich czarnymi / przezroczystymi obrazami i zmiana trybu renderowania sprawi, że Twoje życie będzie nawet 10 razy lepsze.

15
Wydaje się, że występuje błąd z włączonym kolorem odcienia UIImageView, więc kolor odcienia nie zawsze jest wyświetlany podczas uruchamiania aplikacji.
Fogh

@Fogh Miałem też kilka niespójnych błędów. Czy ustawienie koloru odcienia programowo rozwiązuje ten problem?
Anthony Mattox

2
Mogę potwierdzić, że wystąpił problem podczas ustawiania koloru odcienia w IB. Ustawienie to działa programowo. Zgłosiłam dla niego błąd o numerze 20305518.
Nikolay Derkach

1
@AxelGuilmin Yup. Właściwie używany jest tylko kanał alfa, więc może to być dowolny kolor, o ile przezroczystość jest taka, jak chcesz.
Anthony Mattox

1
Działa teraz z Xcode 7.3 (7D175)! Chociaż zaakceptowana odpowiedź jest bardzo intuicyjnym obejściem, wolę tę odpowiedź.
Nstein

43

Używanie trybu renderowania szablonu z UIImageView w scenorysie lub xib jest bardzo błędne, zarówno w systemie iOS 7, jak i iOS 8.

W systemie iOS 7

UIImage nie jest poprawnie dekodowany z storyboardu / xib. Jeśli sprawdzisz imageView.image.renderingModewłaściwość w viewDidLoadmetodzie, zauważysz, że tak jest zawsze UIImageRenderingModeAutomatic, nawet jeśli ustawisz ją na Renderuj jako obraz szablonu w pliku xcassets.

Aby obejść ten problem, musisz ręcznie ustawić tryb renderowania:

self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

W systemie iOS 8

UIImage jest prawidłowo zdekodowany, a jego renderingModewłaściwość odzwierciedla to, co zostało wybrane w pliku xcassets, ale obraz nie jest zabarwiony.

Aby obejść ten problem, masz dwie możliwości:

  1. Ustaw tintColorwłaściwość w atrybutach środowiska wykonawczego zdefiniowanych przez użytkownika zamiast w panelu inspektora atrybutów.

lub

  1. Ręcznie zresetuj odcień Kolor:
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;

Możesz wybrać preferowaną opcję, obie odpowiednio zabarwiają obraz.

(Jeśli kompilujesz z Xcode 6.2, wystarczy zrobić self.imageView.tintColor = self.imageView.tintColor;to, ale to już nie działa, jeśli kompilujesz z Xcode 6.3)

Wniosek

Jeśli chcesz obsługiwać zarówno iOS 7, jak i iOS 8, będziesz potrzebować obu obejść. Jeśli musisz obsługiwać tylko iOS 8, potrzebne jest tylko jedno obejście.


2
Dzięki. Tylko obejście nr 2 działa dla mnie w Xcode 7 i iOS 8.
surfrider

3
Potwierdzam, że obejście dla iOS 8 jest możliwe również dla iOS 9.
Michael Pirotte

1
Zdecydowanie widzę to samo w Xcode 7 - obejście atrybutu użytkownika było w porządku. Dzięki!
Geoffrey Wiseman

ręczne resetowanie tintColor w awakeFromNib zrobiło to! (obraz został ustawiony jako szablon w katalogu .xcassets, w przeciwnym razie musiałbyś utworzyć obraz szablonu z oryginału). Dzięki!!
horseshoe7

15

Ustawienie imageView RenderingMode tak, aby używał koloru tinta w serii ujęć, można zredukować do jednowierszowego:

[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];

Następnie obraz i kolor tinta można ustawić w Storyboard.


13

Możesz naprawić problemy z .xib za pomocą rozszerzenia:

import UIKit

// fixing Bug in XCode
// http://openradar.appspot.com/18448072
extension UIImageView {
    override open func awakeFromNib() {
        super.awakeFromNib()
        self.tintColorDidChange()
    }
}

Źródło: https://gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac

Niesamowite, ten błąd istnieje już od 4-5 lat.


3
To powinno być wybrane jako odpowiedź
farzadshbfn

Wciąż jest to błąd, który nadal rozwiązuje go od wersji iOS 12.0.
Sam Soffes

Wciąż błąd w iOS 12.1
Cesare

Nierealne faceci, nierealne.
Mat

8

Nie możesz ustawić renderingModeani z, storyboardani xib. Może uzyskać dostęp programowo.

dawny:

UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

3
Myślę, że zrobiłeś małe literówki w swoim kodzie. Druga linia powinna byćUIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Artem Stepanenko

8

Ustaw tintColor & Class w Storyboard.

//
//  TintColoredImageView.swift
//  TintColoredImageView
//
//  Created by Dmitry Utmanov on 14/07/16.
//  Copyright © 2016 Dmitry Utmanov. All rights reserved.
//

import UIKit

@IBDesignable class TintColoredImageView: UIImageView {

    override var image: UIImage? {
        didSet {
            let _tintColor = self.tintColor
            self.tintColor = nil
            self.tintColor = _tintColor
        }
    }


    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialize()
    }

    override init(image: UIImage?) {
        super.init(image: image)
        initialize()
    }

    override init(image: UIImage?, highlightedImage: UIImage?) {
        super.init(image: image, highlightedImage: highlightedImage)
        initialize()
    }

    func initialize() {
        let _tintColor = self.tintColor
        self.tintColor = nil
        self.tintColor = _tintColor
    }

}

To jedyna odpowiedź, która zadziałała na nowym jegu. Dziękuję Ci.
Simon Moshenko

Nie działa dla mnie z jakiegoś dziwnego powodu ... Czy to ma zaktualizować kolor w storyboardzie?
Cesare

4

Bardzo łatwo to naprawić

Po prostu utwórz klasę UIImageViewPDF i użyj jej w swoim storyboardzie

IB_DESIGNABLE
@interface UIImageViewPDF : UIImageView

@end

@implementation UIImageViewPDF

- (void) didMoveToSuperview
{
    [super didMoveToSuperview];
    self.image = [self.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    id color = self.tintColor;
    self.tintColor = color;
}

@end

3

Innym rozwiązaniem jest utworzenie UIImageViewpodklasy:

final class TemplateImageView: UIImageView {
    override func awakeFromNib() {
        super.awakeFromNib()
        guard let oldImage = image else { return }
        image = nil
        image = oldImage.withRenderingMode(.alwaysTemplate)
    }
}

Następnie po prostu ustaw klasę w Interface Builder na TemplateImageView.


najlepsze rozwiązanie !!
Irshad Mohamed

2

Prosty sposób na ustawienie z Storyboard:

@IBDesignable
public class CustomImageView: UIImageView {
    @IBInspectable var alwaysTemplate: Bool = false {
        didSet {
            if alwaysTemplate {
                self.image = self.image?.withRenderingMode(.alwaysTemplate)
            } else {
                self.image = self.image?.withRenderingMode(.alwaysOriginal)
            }

        }
    }
}

Działa dobrze na iOS 10 i Swift 3


1

W systemie iOS 9 ustawienie tintColorwłaściwości w Interface Builder jest nadal błędne.

Zauważ, że działającym rozwiązaniem oprócz pisania linii bezpośrednio modyfikujących ImageViewwłaściwości jest ustawienie Renderuj jako: Obraz szablonu w katalogu zasobów i wywołanie np .:

[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];

1

Naprawiono ten problem, dodając atrybut runtime tintColorw konstruktorze interfejsu.

UWAGA: Nadal będziesz musiał ustawić renderowanie obrazu jako obrazu szablonu w pliku Images.xcassets.

wprowadź opis obrazu tutaj


0

Jeśli tworzysz IBOutlet, możesz go zmienić w swojej metodzie awakeFromNib w ten sposób ...

self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Chociaż odpowiedź @ Moby'ego jest bardziej poprawna - może być bardziej zwięzła.


1
Pytanie brzmiało, jak to zrobić w scenorysie (lub xib), a nie w kodzie.
Artem Stepanenko

@artem - tak, przepraszam, nie chciałem wnioskować, że mam odpowiedź na Twoje pytanie. Wystarczy wskazać prosty sposób radzenia sobie z tym za pośrednictwem IBOutlet
amergin

0

Szalony ten błąd nadal występuje w iOS 12.1! W przypadku scenorysów / xibs: dodanie tagu do UIImageView może być szybką naprawą.

Swift 4.2

view.viewWithTag(1)?.tintColorDidChange()

0
extension UIImageView {

   @IBInspectable var renderModeTemplate : Bool {
       get{
           return image?.renderingMode == .alwaysTemplate
       }

       set{
          image = image?.withRenderingMode(newValue ? .alwaysTemplate:.alwaysOriginal)
       }
   }
}

W scenorysie wybierz UIImageView i wybierz inspektora, ustaw właściwość renderModeTemplate= On In Storyboard


0

Jak Rudolf również wspomniał powyżej , zdefiniowałbym prostą klasę, taką jak ta:

import UIKit

@IBDesignable class TintImage: UIImageView{
    override func layoutSubviews() {
        super.layoutSubviews()
 
        image = image?.withRenderingMode(.alwaysTemplate)
    }
}

Po tej definicji wystarczy dodać Widok obrazu do scenorysu i wybrać jego klasę niestandardową jako TintImage. Spowoduje to aktywację wyboru „Odcień” w serii ujęć.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.