Можно ли изменить 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
. Это активирует выбор «Оттенок» в раскадровке.