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.