Можно ли изменить UIImage
renderingMode
из раскадровки или редактора xib?
Цель состоит в том, чтобы применить tintColor
к конкретному объекту UIImageView
.
Можно ли изменить UIImage
renderingMode
из раскадровки или редактора xib?
Цель состоит в том, чтобы применить tintColor
к конкретному объекту UIImageView
.
Здесь вы можете сделать это в файлах .xib или раскадровки:
Создайте категорию на 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
Затем в Identity Inspector в файле xib добавьте атрибут runtime:
Вы можете установить режим рендеринга изображения не в файле .xib
, а в библиотеке .xcassets
.
После добавления изображения в библиотеку активов выберите изображение и откройте инспектор атрибутов с правой стороны Xcode. Найдите атрибут "Render As" и установите его в "шаблон".
После настройки режима рендеринга изображения вы можете добавить цвет оттенка в UIImageView
в файле .xib
или .storyboard
, чтобы настроить цвет изображения.
Это устанавливает свойство на изображении везде, где оно используется, а не только в одном файле построителя интерфейса, но почти во всех случаях (с которыми я столкнулся) это поведение, которое вы хотите.
Несколько замечаний:
UIImageView
. Я не очень глубоко заглядывал.UIKitComponents
, таких как изображения в UIButton
и UIBarButtonItem
.Использование режима рендеринга шаблона с UIImageView в раскадровке или xib очень плохо, как на iOS 7, так и на iOS 8.
UIImage неправильно декодируется из раскадровки /xib. Если вы проверите свойство imageView.image.renderingMode
в методе viewDidLoad
, вы заметите, что он всегда UIImageRenderingModeAutomatic
, даже если вы установили его в Render As Template Image в файле 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]];
Затем цвет изображения и оттенка может быть установлен в Раскадке.
Вы не можете установить renderingMode
либо из storyboard
, либо xib
. Он мог получить доступ программным путем.
ex:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
Установите 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
.
В iOS 9 настройка свойства tintColor
в Interface Builder по-прежнему не работает.
Обратите внимание, что рабочим решением, помимо написания строк, непосредственно изменяющих свойства ImageView
, является установка Render As: Template Image в каталоге активов и вызов, например:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
Простой способ установить из раскадровки:
@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
Если вы создаете IBOutlet, вы можете изменить его в своем методе awakeFromNib, например...
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
В то время как ответ @Moby более правильный - это может быть более кратким.