从storyboard / xib文件修改UIImage renderingMode
是否有可能从故事板或xib编辑器修改UIImage
的renderingMode
?
目标是将tintColor
应用于特定的UIImageView
对象。
以下是如何在.xib或storyboard文件中执行此操作的方法:
在UIImageView
上创build一个类别:
@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
然后在xib文件的Identity Inspector中添加一个运行时属性:
您可以将图像呈现模式设置为不在.xcassets
文件中,而是在.xcassets
库中。
将图像添加到资产库后,select图像并打开Xcode右侧的属性检查器。 find属性“渲染为”并将其设置为“模板”。
设置图像的渲染模式后,可以在.storyboard
或.storyboard
文件的UIImageView
中添加色调来调整图像的颜色。
这将设置图像上的属性,而不仅仅是在一个接口生成器文件中,但几乎在所有情况下(我遇到过),这是你想要的行为。
有几件事要注意:
- 图像颜色在界面生成器中看起来并没有改变(从Xcode 6.1.1开始),但是在应用程序运行时会起作用。
- 我经历了这个function的一些bugginess,在一些情况下,我不得不删除并重新添加
UIImageView
。 我没有深究。 - 这也适用于其他
UIKitComponents
如UIButton
和UIBarButtonItem
的图像。 - 如果您的资产库中有一堆不可见的白色图像,使它们成为黑色/透明图像并更改渲染模式将使您的生活质量提高10倍。
在iOS 7和iOS 8上,在故事板或xib中将UIImageView用于模板呈现模式非常麻烦。
在iOS 7上
UIImage没有从故事板/ xib正确解码。 如果您在viewDidLoad
方法中检查了UIImageRenderingModeAutomatic
,即使将其设置为“在xcassets文件中渲染为模板图像” ,您也会注意到它始终是UIImageRenderingModeAutomatic。
要解决方法,您必须手动设置呈现模式:
self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
在iOS 8上
UIImage被正确解码,其renderingMode
属性反映了在xcassets文件中select的内容,但图像没有着色。
要解决这个问题,你有两个select:
- 在“ 用户定义的运行时属性”中设置
tintColor
属性,而不是“属性”检查器窗格。
要么
- 手动重置tintColor:
UIColor *tintColor = self.imageView.tintColor; self.imageView.tintColor = nil; self.imageView.tintColor = tintColor;
你可以select你喜欢的选项,都适当的色调图像。
(如果使用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]];
然后,图像和色彩的颜色都可以在故事板中设置。
你不能从storyboard
或xib
设置renderingMode
。 它可以通过程序访问。
例如:
UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"]; selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
在Storyboard中设置tintColor&Class。
// // 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 } }
这很容易修复
只需创buildUIImageViewPDF类并在故事板中使用它
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
另一个解决scheme是创build一个UIImageView
子类:
final class TemplateImageView: UIImageView { override func awakeFromNib() { super.awakeFromNib() guard let oldImage = image else { return } image = nil image = oldImage.withRenderingMode(.alwaysTemplate) } }
然后,只需将Interface Builder中的类设置为TemplateImageView
。
在iOS 9中,在Interface Builder中设置tintColor
属性仍然有问题。
请注意,除了直接修改ImageView
属性之外,一个工作解决scheme是在资产目录中设置“渲染为:模板图像”,然后调用例如:
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
如果你创build一个IBOutlet,你可以在你的awakeFromNib方法中改变它,像这样…
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
虽然@ Moby的答案是更正确的 – 这可能会更简洁。
从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) } } } }
在iOS 10和Swift 3上运行良好