【问题标题】:Modify UIImage renderingMode from a storyboard/xib file从 storyboard/xib 文件修改 UIImage renderingMode
【发布时间】:2013-10-31 07:00:11
【问题描述】:

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

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

【问题讨论】:

    标签: ios ios7 xcode-storyboard


    【解决方案1】:

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

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

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

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

    需要注意的几点:

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

    【讨论】:

    • UIImageView 上的色调颜色似乎存在错误,因此在运行应用程序时并不总是显示色调颜色。
    • @Fogh 我也遇到过类似的一些不一致的错误。以编程方式设置色调颜色是否可以解决此问题?
    • 我可以确认在 IB 中设置色调颜色时存在问题。以编程方式设置它有效。我为此提交了一个错误 #20305518。
    • @AxelGuilmin 是的。实际上只使用了 alpha 通道,所以它可以是任何颜色,只要透明度是你想要的。
    • 现在可以与 Xcode 7.3 (7D175) 一起使用!尽管接受的答案是一种非常直观的解决方法,但我更喜欢这个答案。
    【解决方案2】:

    您可以在 .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中,添加一个runtime属性:

    【讨论】:

    • 我喜欢这个答案,因为它是对问题的回答。
    • 我更愿意创建一个 UIImageView 子类而不是进行键值设置。因为,它更容易设置,我们可以避免将数字设置为枚举值。例如:`@implementation TemplateRenderingImageView -(id)initWithCoder:(NSCoder *)aDecoder{ self = [super initWithCoder:aDecoder]; if (self) { self.image = [self.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; } 返回自我; } @end`
    • 很好的答案!截图很有帮助。
    • 当然不能与 Launch Screen.xib 一起使用,因为您不能使用用户定义的运行时属性。
    • hardcoding 2 as a value is bad bad bad.. 使用 xcassets 目录是正确答案。
    【解决方案3】:

    在 iOS 7 和 iOS 8 上,在 Storyboard 或 xib 中使用带有 UIImageView 的模板渲染模式非常有问题。

    在 iOS 7 上

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

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

    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,则只需要一种解决方法。

    【讨论】:

    • 谢谢。只有解决方法 #2 在 Xcode 7 和 iOS 8 中对我有用。
    • 我确认 iOS 8 的解决方法也适用于 iOS 9。
    • 我肯定在 Xcode 7 上看到了同样的情况——用户属性解决方法很好。谢谢!
    • 在 awakeFromNib 中手动重置 tintColor 做到了! (图像也被设置为 .xcassets 目录中的模板,否则您必须从原始图像中制作模板图像)。谢谢!!
    【解决方案4】:

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

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

    然后图片和色调颜色都可以在Storyboard中设置。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 这应该被选作答案
      • 仍然是一个错误,这仍然在 iOS 12.0 中修复。
      • 在 iOS 12.1 中仍然是一个错误
      • 虚幻的家伙,虚幻的。
      【解决方案6】:

      您不能从storyboardxib 设置renderingMode。它可以通过编程方式访问。

      例如:

      UIImage *unSeletedImage = [UIImage imageNamed:@"UnSelected.png"];
      selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
      

      【讨论】:

      • 我认为,您的代码中出现了一些小错别字。第二行应该是UIImage *selectedImage = [unSeletedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
      【解决方案7】:

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

      【讨论】:

      • 这是唯一适用于新 swift 的答案。谢谢。
      • 由于某些奇怪的原因对我不起作用...是否应该更新情节提要中的颜色?
      【解决方案8】:

      很容易修复

      只需创建类 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
      

      【讨论】:

        【解决方案9】:

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

        【讨论】:

        • 最佳解决方案!!
        【解决方案10】:

        从情节提要中设置的简单方法:

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

        【讨论】:

          【解决方案11】:

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

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

          【讨论】:

            【解决方案12】:

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

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

            [[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
            

            【讨论】:

              【解决方案13】:

              如果您创建一个 IBOutlet,您可以像这样在 awakeFromNib 方法中更改它...

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

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

              【讨论】:

              • 问题是如何在故事板(或 xib)中做到这一点,而不是在代码中。
              • @artem - 是的,对不起,我并不是想推断我对你的问题有答案。仅指出通过 IBOutlet 处理此问题的简单方法
              【解决方案14】:

              这个 bug 还在 iOS 12.1 中!对于storyboards/xibs:给UIImageView添加一个标签可以快速解决。

              斯威夫特 4.2

              view.viewWithTag(1)?.tintColorDidChange()
              

              【讨论】:

                【解决方案15】:
                extension UIImageView {
                
                   @IBInspectable var renderModeTemplate : Bool {
                       get{
                           return image?.renderingMode == .alwaysTemplate
                       }
                
                       set{
                          image = image?.withRenderingMode(newValue ? .alwaysTemplate:.alwaysOriginal)
                       }
                   }
                }
                
                

                在storyboard中选择UIImageView并选择inspector,设置属性renderModeTemplate = On In Storyboard

                【讨论】:

                  【解决方案16】:

                  正如鲁道夫也提到above,我会定义一个简单的类,像这样:

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

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

                  【讨论】:

                    猜你喜欢
                    • 2011-12-09
                    • 2013-08-26
                    • 2016-12-10
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-04-29
                    • 2013-11-04
                    • 1970-01-01
                    • 2012-01-16
                    相关资源
                    最近更新 更多