Modify UIImage renderingMode from a storyboard/xib file

前端 未结 16 2187
别那么骄傲
别那么骄傲 2020-12-02 08:00

Is it possible to modify a UIImage\'s renderingMode from a storyboard or xib editor?

The goal is to apply tintColor to the par

相关标签:
16条回答
  • 2020-12-02 08:29

    Here's how you can do it in .xib or storyboard files:

    (Obj-C) Create a category on 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) Create an extension for 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)
        }
    }
    

    Then in the Identity Inspector in the xib file, add a runtime attribute:

    enter image description here

    0 讨论(0)
  • 2020-12-02 08:29

    Using the template rendering mode with a UIImageView in a storyboard or xib is very buggy, both on iOS 7 and iOS 8.

    On iOS 7

    The UIImage is not properly decoded from the storyboard/xib. If you inspect the imageView.image.renderingMode property in the viewDidLoad method, you will notice that it is always UIImageRenderingModeAutomatic, even if you set it to Render As Template Image in your xcassets file.

    To workaround, you have to manually set the rendering mode:

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

    On iOS 8

    The UIImage is properly decoded and its renderingMode property reflects what was chosen in the xcassets file but the image is not tinted.

    To workaround, you have two options:

    1. Set the tintColor property in the User Defined Runtime Attributes instead of the Attributes inspector pane.

    or

    1. Manually reset the tintColor:
    UIColor *tintColor = self.imageView.tintColor;
    self.imageView.tintColor = nil;
    self.imageView.tintColor = tintColor;
    

    You can pick your preferred option, both properly tint the image.

    (If you are compiling with Xcode 6.2, just doing self.imageView.tintColor = self.imageView.tintColor; is enough but this doesn’t work anymore if you are compiling with Xcode 6.3)

    Conclusion

    If you need to support both iOS 7 and iOS 8, you’ll need both workarounds. If you only have to support iOS 8, only one workaround is needed.

    0 讨论(0)
  • 2020-12-02 08:29

    Setting imageView RenderingMode to use the tint color in the storyboard can be reduced to a one-liner:

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

    Then the image and tint color can all be set in the Storyboard.

    0 讨论(0)
  • 2020-12-02 08:34

    If you create an IBOutlet you can change it in your awakeFromNib method like so...

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

    While @Moby's answer is more correct - this might be more succinct.

    0 讨论(0)
  • 2020-12-02 08:34

    Crazy this bug is still in iOS 12.1! For storyboards/xibs: Adding a tag to the UIImageView can be a quick fix.

    Swift 4.2

    view.viewWithTag(1)?.tintColorDidChange()
    
    0 讨论(0)
  • 2020-12-02 08:35

    Simple way to be set from 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)
                }
    
            }
        }
    }
    

    Works fine on iOS 10 and Swift 3

    0 讨论(0)
提交回复
热议问题