É possível modificar um UIImage
's renderingMode
de um editor de storyboard ou xib?
O objetivo é aplicar tintColor
ao UIImageView
objeto específico .
É possível modificar um UIImage
's renderingMode
de um editor de storyboard ou xib?
O objetivo é aplicar tintColor
ao UIImageView
objeto específico .
Respostas:
Veja como você pode fazer isso em arquivos .xib ou storyboard:
(Obj-C) Crie uma categoria em 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) Crie uma extensão para 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)
}
}
Em seguida, no Identity Inspector do arquivo xib, adicione um atributo runtime:
Você pode definir o modo de renderização da imagem não no .xib
arquivo, mas em uma .xcassets
biblioteca.
Depois de adicionar uma imagem a uma biblioteca de ativos, selecione a imagem e abra o inspetor de atributos no lado direito do Xcode. Encontre o atributo 'Renderizar como' e defina-o como 'template'.
Depois de definir o modo de renderização de uma imagem, você pode adicionar uma cor de matiz UIImageView
em um arquivo .xib
ou .storyboard
para ajustar a cor da imagem.
Isso define a propriedade na imagem onde quer que seja usada, em vez de apenas em um arquivo do construtor de interface, mas em quase todos os casos (que encontrei) este é o comportamento que você deseja.
Algumas coisas a serem observadas:
UIImageView
. Eu não olhei tão profundamente.UIKitComponents
imagens, como em UIButton
'se UIBarButtonItem
' s.UIImageView
, então a cor da tonalidade nem sempre é mostrada ao executar o aplicativo.
Usar o modo de renderização de modelo com um UIImageView em um storyboard ou xib é muito problemático, tanto no iOS 7 quanto no iOS 8.
O UIImage não foi decodificado corretamente do storyboard / xib. Se você inspecionar a imageView.image.renderingMode
propriedade no viewDidLoad
método, perceberá que é sempre UIImageRenderingModeAutomatic
, mesmo se você configurá-la para Render As Template Image em seu arquivo xcassets.
Para contornar o problema, você deve definir manualmente o modo de renderização:
self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
O UIImage é decodificado corretamente e sua renderingMode
propriedade reflete o que foi escolhido no arquivo xcassets, mas a imagem não é colorida.
Para contornar o problema, você tem duas opções:
tintColor
propriedade nos Atributos de Tempo de Execução Definidos pelo Usuário em vez do painel do inspetor Atributos.ou
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;
Você pode escolher sua opção preferida, tanto tingir corretamente a imagem.
(Se você estiver compilando com o Xcode 6.2, basta fazer self.imageView.tintColor = self.imageView.tintColor;
é suficiente, mas isso não funciona mais se você estiver compilando com o Xcode 6.3)
Se precisar de suporte para iOS 7 e iOS 8, você precisará de ambas as soluções alternativas. Se você só precisa oferecer suporte ao iOS 8, apenas uma solução alternativa é necessária.
A configuração de imageView RenderingMode para usar a cor de matiz no storyboard pode ser reduzida a uma linha:
[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
Então, a imagem e a cor da tonalidade podem ser definidas no Storyboard.
Você pode corrigir problemas .xib com uma extensão:
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
Incrível, esse bug já existe há 4-5 anos.
Você não pode definir renderingMode
de storyboard
ou xib
. Ele pode acessar programaticamente.
ex:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Defina tintColor e classe no 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
}
}
É muito fácil de consertar
Basta criar a classe UIImageViewPDF e usá-la em seu 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
Outra solução é criar uma UIImageView
subclasse:
final class TemplateImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
guard let oldImage = image else { return }
image = nil
image = oldImage.withRenderingMode(.alwaysTemplate)
}
}
Em seguida, defina a classe no Interface Builder como TemplateImageView
.
Maneira simples de definir a partir do 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)
}
}
}
}
Funciona bem no iOS 10 e Swift 3
Na configuração do iOS 9, a tintColor
propriedade no Interface Builder ainda apresenta erros.
Observe que uma solução de trabalho além de escrever linhas que modificam diretamente as ImageView
propriedades é definir Render As: Template Image no catálogo de ativos e chamar, por exemplo:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
Resolvi esse problema adicionando o atributo runtime tintColor
no construtor de interface.
NOTA: Você ainda precisará definir sua imagem para ser renderizada como uma imagem de modelo em seu arquivo Images.xcassets.
Se você criar um IBOutlet, você pode alterá-lo em seu método awakeFromNib assim ...
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Embora a resposta de @Moby seja mais correta - pode ser mais sucinta.
Louco esse bug ainda está no iOS 12.1! Para storyboards / xibs: Adicionar uma tag ao UIImageView pode ser uma solução rápida.
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)
}
}
}
No storyboard, selecione UIImageView e selecione o inspetor, defina a propriedade renderModeTemplate
= On
No Storyboard