Можно ли изменить UIImage«S renderingModeиз раскадровки или XIb редактор?
Цель - применить tintColorк конкретному UIImageViewобъекту.
Можно ли изменить UIImage«S renderingModeиз раскадровки или XIb редактор?
Цель - применить tintColorк конкретному UIImageViewобъекту.
Ответы:
Вот как это можно сделать в файлах .xib или раскадровке:
(Obj-C) Создайте категорию на 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) Создайте расширение для 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)
}
}
Затем в Identity Inspector в файле xib добавьте атрибут времени выполнения:

Вы можете установить режим рендеринга изображения не в .xibфайле, а в .xcassetsбиблиотеке.
После добавления изображения в библиотеку ресурсов выберите изображение и откройте инспектор атрибутов в правой части Xcode. Найдите атрибут «Визуализировать как» и установите для него «шаблон».
После установки режима рендеринга изображения вы можете добавить цвет оттенка UIImageViewв файл .xibили, .storyboardчтобы настроить цвет изображения.
Это устанавливает свойство на изображении, где бы оно ни использовалось, а не только в одном файле построителя интерфейса, но почти во всех случаях (с которыми я сталкивался) это именно то поведение, которое вам нужно.

Несколько замечаний:
UIImageView. Я не вникал в это глубоко.UIKitComponentsнапример изображениями в UIButton's и UIBarButtonItem'.UIImageView, поэтому цвет оттенка не всегда отображается при запуске приложения.
Использование режима рендеринга шаблона с UIImageView в раскадровке или xib очень ошибочно, как на iOS 7, так и на iOS 8.
UIImage неправильно декодируется из раскадровки / xib. Если вы проверите imageView.image.renderingModeсвойство в viewDidLoadметоде, вы заметите, что оно всегда UIImageRenderingModeAutomatic, даже если вы установите для него значение « Визуализировать как изображение шаблона» в файле xcassets.
Чтобы обойти эту проблему, вам необходимо вручную установить режим рендеринга:
self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImage правильно декодирован, и его renderingModeсвойство отражает то, что было выбрано в файле xcassets, но изображение не окрашено.
Для обходного пути у вас есть два варианта:
tintColorсвойство в определяемых пользователем атрибутах времени выполнения, а не на панели инспектора атрибутов.или
UIColor *tintColor = self.imageView.tintColor;
self.imageView.tintColor = nil;
self.imageView.tintColor = tintColor;
Вы можете выбрать понравившийся вариант, как правильно подкрасить изображение.
(Если вы компилируете с Xcode 6.2, достаточно просто сделать self.imageView.tintColor = self.imageView.tintColor;, но это больше не работает, если вы компилируете с Xcode 6.3)
Если вам нужно поддерживать как iOS 7, так и iOS 8, вам понадобятся оба обходных пути. Если вам нужно поддерживать только iOS 8, необходимо только одно временное решение.
Настройка imageView RenderingMode для использования цвета оттенка в раскадровке может быть уменьшена до однострочного:
[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
Затем изображение и цвет оттенка можно установить в раскадровке.
Вы можете исправить проблемы .xib с помощью расширения:
import UIKit
// fixing Bug in XCode
// http://openradar.appspot.com/18448072
extension UIImageView {
override open func awakeFromNib() {
super.awakeFromNib()
self.tintColorDidChange()
}
}
Источник: https://gist.github.com/buechner/3b97000a6570a2bfbc99c005cb010bac
Удивительно, но эта ошибка существует уже 4-5 лет.
Вы не можете установить renderingModeни из, storyboardни xib. Он мог получить доступ программно.
пример:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Установите tintColor и класс в раскадровке.
//
// 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
}
}
Это очень легко исправить
Просто создайте класс UIImageViewPDF и используйте его в своей раскадровке.
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
Другое решение - создать UIImageViewподкласс:
final class TemplateImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
guard let oldImage = image else { return }
image = nil
image = oldImage.withRenderingMode(.alwaysTemplate)
}
}
Затем просто установите класс в Интерфейсном Разработчике на TemplateImageView.
Простой способ установки из раскадровки:
@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)
}
}
}
}
Прекрасно работает на iOS 10 и Swift 3
В iOS 9 установка tintColor свойства в Интерфейсном Разработчике все еще содержит ошибки.
Обратите внимание, что рабочим решением помимо написания строк, непосредственно изменяющих ImageViewсвойства, является установка Render As: Template Image в каталоге ресурсов и вызов, например:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
Если вы создаете IBOutlet, вы можете изменить его в своем методе awakeFromNib следующим образом ...
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
Хотя ответ @Moby более правильный - он может быть более сжатым.
Безумно, эта ошибка все еще присутствует в iOS 12.1! Для раскадровок / xibs: добавление тега в UIImageView может быть быстрым решением.
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)
}
}
}
В раскадровке выберите UIImageView и выберите инспектор, установите свойство renderModeTemplate= On
In Storyboard
Как упоминал выше Рудольф , я бы определил простой класс, например:
import UIKit
@IBDesignable class TintImage: UIImageView{
override func layoutSubviews() {
super.layoutSubviews()
image = image?.withRenderingMode(.alwaysTemplate)
}
}
После этого определения просто добавьте представление изображения в раскадровку и выберите его настраиваемый класс как TintImage. Это активирует выбор «Оттенок» в раскадровке.