98

是否可以从情节提要或 xib 编辑器修改 a UIImagerenderingMode

目标是应用于tintColor特定UIImageView对象。

4

16 回答 16

204

您可以不在.xib文件中设置图像渲染模式,而是在.xcassets库中设置。

将图像添加到资产库后,选择图像并打开 Xcode 右侧的属性检查器。找到属性“渲染为”并将其设置为“模板”。

UIImageView设置图像的渲染模式后,您可以在文件.xib或文件中添加色调颜色.storyboard以调整图像颜色。

这会在图像上的任何位置设置属性,而不仅仅是在一个界面构建器文件中,但在几乎所有情况下(我遇到过),这都是您想要的行为。

显示图像属性检查器的 Xcode 屏幕截图

需要注意的几点:

  • 图像颜色在界面生成器中似乎没有改变(从 Xcode 6.1.1 开始),但在应用程序运行时会起作用。
  • 我在使用此功能时遇到了一些问题,在某些情况下,我不得不删除并重新添加UIImageView. 我没有深入研究过。
  • 这也适用于其他UIKitComponents图像,例如UIButton's 和UIBarButtonItem's 中的图像。
  • 如果您的资产库中有一堆不可见的白色图像,则将它们设为黑色/透明图像并更改渲染模式将使您的生活提高 10 倍。
于 2015-01-02T18:59:50.357 回答
102

以下是在 .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)
    }
}

然后在 xib 文件的 Identity Inspector 中,添加一个运行时属性:

在此处输入图像描述

于 2014-05-12T17:31:29.540 回答
43

在 iOS 7 和 iOS 8 上,在故事板或 xib 中使用带有 UIImageView 的模板渲染模式是非常错误的。

在 iOS 7 上

UIImage 未从情节提要/xib 正确解码。如果您检查方法imageView.image.renderingMode中的属性viewDidLoad,您会注意到它总是UIImageRenderingModeAutomatic,即使您在 xcassets 文件中将其设置为Render As Template Image也是如此。

要解决此问题,您必须手动设置渲染模式:

self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

在 iOS 8 上

UIImage 已正确解码,其renderingMode属性反映了 xcassets 文件中选择的内容,但图像未着色。

要解决此问题,您有两种选择:

  1. tintColor用户定义的运行时属性而不是属性检查器窗格中设置属性。

或者

  1. 手动重置 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,则只需要一种解决方法。

于 2015-06-09T19:47:02.903 回答
15

将 imageView RenderingMode 设置为使用情节提要中的 tint 颜色可以简化为单行:

[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];

然后可以在情节提要中设置图像和色调颜色。

于 2014-04-23T17:12:54.193 回答
13

您可以通过扩展修复 .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 年了。

于 2018-01-16T17:06:12.533 回答
8

您不能设置renderingModefromstoryboardxib. 它可以通过编程方式访问。

前任:

UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
于 2013-10-22T12:22:17.340 回答
8

在 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
    }

}
于 2016-07-14T10:34:06.057 回答
4

很容易修复

只需创建类 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
于 2015-09-04T20:33:15.463 回答
3

另一种解决方案是创建一个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.

于 2017-07-12T22:54:04.050 回答
2

从 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 上运行良好

于 2017-09-12T09:43:34.987 回答
2

我通过tintColor在界面生成器中添加运行时属性解决了这个问题。

注意:您仍然需要在 Images.xcassets 文件中将图像设置为模板图像。

在此处输入图像描述

于 2019-02-25T08:35:05.820 回答
1

在 iOS 9 中,tintColor在 Interface Builder 中设置属性仍然存在问题。

请注意,除了编写直接修改ImageView属性的行之外,一个可行的解决方案是在资产目录中设置渲染为:模板图像,并调用例如:

[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
于 2015-12-23T22:04:12.737 回答
0

如果你创建一个 IBOutlet 你可以在你的 awakeFromNib 方法中改变它,就像这样......

self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

虽然@Moby 的回答更正确——这可能更简洁。

于 2014-10-23T08:43:14.180 回答
0
extension UIImageView {

   @IBInspectable var renderModeTemplate : Bool {
       get{
           return image?.renderingMode == .alwaysTemplate
       }

       set{
          image = image?.withRenderingMode(newValue ? .alwaysTemplate:.alwaysOriginal)
       }
   }
}

在情节提要中选择 UIImageView 并选择检查器,设置属性renderModeTemplate=On 在情节提要中

于 2020-02-25T06:10:29.930 回答
0

疯狂的这个 bug 还在 iOS 12.1 中!对于故事板/xib:向 UIImageView 添加标签可以快速修复。

斯威夫特 4.2

view.viewWithTag(1)?.tintColorDidChange()
于 2018-11-11T05:15:04.523 回答
0

正如鲁道夫在上面也提到的,我会定义一个简单的类,如下所示:

import UIKit

@IBDesignable class TintImage: UIImageView{
    override func layoutSubviews() {
        super.layoutSubviews()
 
        image = image?.withRenderingMode(.alwaysTemplate)
    }
}

在此定义之后,只需将图像视图添加到情节提要并选择其自定义类为TintImage. 这将激活情节提要中的“色调”选择。

于 2020-08-27T13:55:59.710 回答