E 'possibile modificare un UIImage
's renderingMode
da un editor di storyboard o XI ter?
L'obiettivo è applicare all'oggetto tintColor
particolare UIImageView
.
E 'possibile modificare un UIImage
's renderingMode
da un editor di storyboard o XI ter?
L'obiettivo è applicare all'oggetto tintColor
particolare UIImageView
.
Risposte:
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:
È possibile impostare la modalità di rendering dell'immagine non nel .xib
file, ma in una .xcassets
libreria.
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 UIImageView
in a .xib
o .storyboard
per 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.
Alcune cose da notare:
UIImageView
. Non l'ho approfondito.UIKitComponents
, come le immagini in UIButton
"e UIBarButtonItem
".UIImageView
, quindi il colore della tinta non viene sempre mostrato durante l'esecuzione dell'app.
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.
L'UIImage non è stato decodificato correttamente dallo storyboard / xib. Se controlli la imageView.image.renderingMode
proprietà nel viewDidLoad
metodo, 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];
L'UIImage è correttamente decodificato e la sua renderingMode
proprietà riflette ciò che è stato scelto nel file xcassets ma l'immagine non è colorata.
Per risolvere il problema, hai due opzioni:
tintColor
proprietà negli attributi di runtime definiti dall'utente invece che nel pannello di ispezione Attributi.o
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)
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.
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.
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.
Non puoi impostare renderingMode
né da storyboard
o xib
. Potrebbe accedere in modo programmatico.
ex:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
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
}
}
È 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
Un'altra soluzione è creare una UIImageView
sottoclasse:
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
.
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
In iOS 9 l'impostazione della tintColor
proprietà in Interface Builder è ancora buggata.
Si noti che una soluzione funzionante oltre a scrivere righe che modificano direttamente le ImageView
proprietà è impostare Render As: Template Image nel catalogo degli asset e chiamare ad esempio:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
Ho risolto questo problema aggiungendo l'attributo di runtime tintColor
nel generatore di interfacce.
NOTA: sarà comunque necessario impostare il rendering dell'immagine come immagine modello nel file Images.xcassets.
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.
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()
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