Modifica UIImage renderingMode da un file storyboard / xib


93

E 'possibile modificare un UIImage's renderingModeda un editor di storyboard o XI ter?

L'obiettivo è applicare all'oggetto tintColorparticolare UIImageView.

Risposte:


101

Ecco come puoi farlo nei file .xib o storyboard:

(Obj-C) Crea una categoria su 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) Crea un'estensione per 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)
    }
}

Quindi nell'Identity Inspector nel file xib, aggiungi un attributo di runtime:

inserisci qui la descrizione dell'immagine


44
Quello che mi piace di questa risposta è che è una risposta alla domanda.
Algal

1
Preferirei creare una sottoclasse UIImageView piuttosto che eseguire l'impostazione del valore chiave. Perché è più facile da configurare e potremmo evitare l'impostazione del numero sul valore di enumerazione. Ad esempio: `@implementation TemplateRenderingImageView - (id) initWithCoder: (NSCoder *) aDecoder {self = [super initWithCoder: aDecoder]; if (self) {self.image = [self.image imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]; } return self; } @ end`
john fantasy

1
Bella risposta! Gli screenshot sono stati utili.
BigSauce

1
Ovviamente non funziona con Launch Screen.xib perché non è possibile utilizzare attributi di runtime definiti dall'utente con esso.
Steve Moser

3
hardcoding 2 come valore è male male male .. L'uso del catalogo xcassets è la risposta giusta.
tGilani

198

È possibile impostare la modalità di rendering dell'immagine non nel .xibfile, ma in una .xcassetslibreria.

Dopo aver aggiunto un'immagine a una libreria di risorse, seleziona l'immagine e apri l'ispettore degli attributi sul lato destro di Xcode. Trova l'attributo "Rendering come" e impostalo su "modello".

Dopo aver impostato la modalità di rendering di un'immagine, è possibile aggiungere un colore di tinta al file UIImageViewin a .xibo .storyboardper regolare il colore dell'immagine.

Questo imposta la proprietà sull'immagine ovunque sia utilizzata piuttosto che in un solo file di creazione dell'interfaccia, ma in quasi tutti i casi (che ho riscontrato) questo è il comportamento che desideri.

Screenshot di Xcode che mostra l'ispettore degli attributi per un'immagine

Alcune cose da notare:

  • Il colore dell'immagine non sembrerà essere cambiato in Interface Builder (a partire da Xcode 6.1.1) ma funzionerà quando l'applicazione viene eseguita.
  • Ho riscontrato dei problemi con questa funzione e in alcune situazioni ho dovuto rimuovere e aggiungere nuovamente il file UIImageView. Non l'ho approfondito.
  • Funziona benissimo anche su altri UIKitComponents, come le immagini in UIButton"e UIBarButtonItem".
  • Se hai molte immagini bianche invisibili nella tua libreria di risorse, renderle immagini nere / trasparenti e cambiare la modalità di rendering renderà la tua vita fino a 10 volte migliore.

15
Sembra che ci sia un bug con il colore della tinta acceso UIImageView, quindi il colore della tinta non viene sempre mostrato durante l'esecuzione dell'app.
Nebbia

@ Fogh Ho avuto anche alcuni bug incoerenti come quello. L'impostazione del colore della tinta a livello di codice risolve questo problema?
Anthony Mattox

2
Posso confermare che c'è un problema durante l'impostazione del colore della tinta in IB. L'impostazione a livello di codice funziona. Ho presentato un bug # 20305518 per questo.
Nikolay Derkach

1
@AxelGuilmin Sì. In realtà viene utilizzato solo il canale alfa, quindi potrebbe essere qualsiasi colore purché la trasparenza sia quella desiderata.
Anthony Mattox,

1
Ora funziona con Xcode 7.3 (7D175)! Sebbene la risposta accettata sia una soluzione molto intuitiva, preferisco invece questa risposta.
nstein

43

L'uso della modalità di rendering del modello con un UIImageView in uno storyboard o xib è molto difettoso, sia su iOS 7 che su iOS 8.

Su iOS 7

L'UIImage non è stato decodificato correttamente dallo storyboard / xib. Se controlli la imageView.image.renderingModeproprietà nel viewDidLoadmetodo, noterai che è sempre UIImageRenderingModeAutomatic, anche se lo imposti su Render As Template Image nel tuo file xcassets.

Per risolvere il problema, devi impostare manualmente la modalità di rendering:

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

Su iOS 8

L'UIImage è correttamente decodificato e la sua renderingModeproprietà riflette ciò che è stato scelto nel file xcassets ma l'immagine non è colorata.

Per risolvere il problema, hai due opzioni:

  1. Imposta la tintColorproprietà negli attributi di runtime definiti dall'utente invece che nel pannello di ispezione Attributi.

o

  1. Ripristina manualmente tintColor:
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;

Puoi scegliere la tua opzione preferita, entrambe colorano correttamente l'immagine.

(Se stai compilando con Xcode 6.2, self.imageView.tintColor = self.imageView.tintColor;è sufficiente farlo ma non funziona più se stai compilando con Xcode 6.3)

Conclusione

Se devi supportare sia iOS 7 che iOS 8, avrai bisogno di entrambe le soluzioni alternative. Se devi supportare solo iOS 8, è necessaria solo una soluzione alternativa.


2
Grazie. L'unica soluzione alternativa n. 2 funziona per me in Xcode 7 e iOS 8.
surfrider

3
Confermo che la soluzione alternativa per iOS 8 è valida anche per iOS 9.
Michael Pirotte

1
Sto sicuramente vedendo la stessa cosa su Xcode 7: la soluzione alternativa per gli attributi utente andava bene. Grazie!
Geoffrey Wiseman

Il ripristino manuale di tintColor in awakeFromNib lo ha fatto! (l'immagine era impostata come modello anche nel catalogo .xcassets, altrimenti dovresti creare un'immagine modello dall'originale). Grazie!!
ferro di cavallo 7

15

L'impostazione di imageView RenderingMode per utilizzare il colore della tinta nello storyboard può essere ridotta a una riga:

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

Quindi l'immagine e il colore della tinta possono essere impostati nello Storyboard.


13

Puoi risolvere i problemi .xib con un'estensione:

import UIKit

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

Fonte: https://gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac

Incredibile, questo bug esiste da circa 4-5 anni.


3
Questo dovrebbe essere selezionato come risposta
farzadshbfn

Ancora un bug e questo lo risolve ancora a partire da iOS 12.0.
Sam Soffes

Ancora un bug in iOS 12.1
Cesare

Ragazzi irreali, irreali.
Sabato

8

Non puoi impostare renderingModené da storyboardo xib. Potrebbe accedere in modo programmatico.

ex:

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

3
Penso che tu abbia fatto piccoli errori di battitura nel tuo codice. La seconda linea dovrebbe essereUIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Artem Stepanenko

8

Imposta tintColor e Class in 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
    }

}

Questa è l'unica risposta che ha funzionato su New Swift. Grazie.
Simon Moshenko

Non funziona per me per qualche strana ragione ... Dovrebbe aggiornare il colore nello storyboard?
Cesare

4

È molto facile da riparare

Basta creare la classe UIImageViewPDF e usarla nel tuo storyboard

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

Un'altra soluzione è creare una UIImageViewsottoclasse:

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

Quindi imposta la classe in Interface Builder su TemplateImageView.


soluzione migliore !!
Irshad Mohamed

2

Modo semplice per essere impostato da 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)
            }

        }
    }
}

Funziona bene su iOS 10 e Swift 3


1

In iOS 9 l'impostazione della tintColorproprietà in Interface Builder è ancora buggata.

Si noti che una soluzione funzionante oltre a scrivere righe che modificano direttamente le ImageViewproprietà è impostare Render As: Template Image nel catalogo degli asset e chiamare ad esempio:

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

1

Ho risolto questo problema aggiungendo l'attributo di runtime tintColornel generatore di interfacce.

NOTA: sarà comunque necessario impostare il rendering dell'immagine come immagine modello nel file Images.xcassets.

inserisci qui la descrizione dell'immagine


0

Se crei un IBOutlet puoi cambiarlo nel tuo metodo awakeFromNib in questo modo ...

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

Mentre la risposta di @ Moby è più corretta, potrebbe essere più succinta.


1
La domanda era come farlo nello storyboard (o xib), non nel codice.
Artem Stepanenko

@artem - sì, scusa, non volevo dedurre di avere una risposta alla tua domanda. Semplicemente sottolineando un modo semplice per affrontare questo problema attraverso un IBOutlet
amergin

0

Pazzesco questo bug è ancora in iOS 12.1! Per storyboard / xib: l'aggiunta di un tag a UIImageView può essere una soluzione rapida.

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

Nello storyboard selezionare UIImageView e selezionare inspector, set property renderModeTemplate= On In Storyboard

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.