ストーリーボードまたはxibエディターからUIImage
のrenderingMode
を変更することはできますか?
目標は、tintColor
を特定のUIImageView
オブジェクトに適用することです。
.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で、ランタイム属性を追加します。
.xib
ファイルではなく、.xcassets
ライブラリで画像レンダリングモードを設定できます。
アセットライブラリに画像を追加した後、画像を選択し、Xcodeの右側にある属性インスペクターを開きます。 「Render As」属性を見つけて、「template」に設定します。
画像のレンダリングモードを設定した後、.xib
または.storyboard
ファイルのUIImageView
に色合いを追加して、画像の色を調整できます。
これにより、1つのインターフェイスビルダーファイルではなく、使用する場所で画像のプロパティが設定されますが、ほとんどすべての場合(これまでに遭遇したことです)、これが目的の動作です。
注意すべきいくつかの点:
UIImageView
を削除して再追加する必要がありました。私はそれを深く見ていません。UIKitComponents
とUIButton
の画像など、他のUIBarButtonItem
でもうまく機能します。ストーリーボードまたはxibのUIImageViewでテンプレートレンダリングモードを使用すると、iOS 7とiOS 8の両方で非常にバグが発生します。
UIImageは、ストーリーボード/ xibから正しくデコードされません。 viewDidLoad
メソッドでimageView.image.renderingMode
プロパティを調べると、Render As Template Imageに設定しても、常にUIImageRenderingModeAutomatic
であることがわかります。 xcassetsファイル。
回避するには、レンダリングモードを手動で設定する必要があります。
self.imageView.image = [self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImageは適切にデコードされ、そのrenderingMode
プロパティはxcassetsファイルで選択されたものを反映しますが、画像は着色されません。
回避策として、次の2つのオプションがあります。
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のみをサポートする必要がある場合、必要な回避策は1つだけです。
ストーリーボードで濃淡色を使用するようにimageView RenderingModeを設定すると、1ライナーに減らすことができます。
[self.imageView setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
次に、画像と色合いをすべてストーリーボードで設定できます。
拡張機能で.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年ほど前から存在しています。
renderingMode
またはstoryboard
からxib
を設定することはできません。プログラムでアクセスできます。
例:
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
}
}
修正はとても簡単です
クラスImageView PDFを作成して、ストーリーボードで使用するだけです
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)
}
}
次に、Interface BuilderでクラスをTemplateImageView
に設定します。
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で正常に動作します
IOS 9では、Interface BuilderのtintColor
プロパティの設定はまだバグがあります。
ImageView
プロパティを直接変更する行を記述する以外の実用的なソリューションは、アセットカタログでRender As:Template Imageを設定し、たとえば以下を呼び出すことです。
[[UIImageView appearanceWhenContainedInInstancesOfClasses:@[[MyView class]]] setTintColor:[UIColor whiteColor]];
クレイジーなこのバグはまだiOS 12.1にあります!ストーリーボード/ xibsの場合:UIImageViewにタグを追加すると簡単に修正できます。
Swift 4.2
view.viewWithTag(1)?.tintColorDidChange()
IBOutletを作成する場合、awakeFromNibメソッドで次のように変更できます。
self.myImageView.image = [self.myImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
@Mobyの答えはより正確ですが、これはもっと簡潔かもしれません。