在下面的例子中,有两个UIImageViews具有相同的设置和相同的模板图像...但一个色调图像,一个不
我重复工作UIImageView
并将其放置而不是另一个并且它有效。这发生在我身上多次,这个解决方案总能奏效,但我仍然想知道我做错了什么?它可以是Xcode错误吗?你有类似的事吗?我有Xcode 8.1。
正如@richardjsimkins所提到的,这似乎至少在某些情况下与约束有关。在我的情况下,我想将图像添加到启动屏幕的中心,因为在这种情况下,我无法以编程方式设置tintColor。我必须找到一个纯粹的Storyboard解决方案。
我发现当使用约束使图像视图居中时没有设置tintColor,即在安全区域中水平/垂直居中,这对应于它没有“与最近邻居间隔”约束。
相反,我添加了一个堆栈视图,其中包含安全区域前导/尾随/顶部/底部的约束,然后将图像视图嵌入到具有对齐中心,分布填充的安全区域中。这解决了与将imageView直接居中于安全区域相同的定位,这使得tintColor生效。
我不喜欢不得不决定使用堆栈视图来强制tintColor工作,但我认为这是一个小而相当干净的解决方法。
我发现的最佳解决方案不需要子类或其他IBInspectable
属性:
import UIKit
extension UIImageView {
override open func awakeFromNib() {
super.awakeFromNib()
tintColorDidChange()
}
}
问题源于没有空状态的色调值(在Storyboard / Interface Builder UI中)。为了让Xcode决定是否应该将色调应用于UIImageView
,似乎还有一个额外的测试。在Xcode中,这显然是通过评估应用于UIImageView
的约束来完成的。据我所知,这个测试没有记录。
如果在UIImageView
的两个(或一个)边上只有“最近邻居间距”约束,那么无论为UIImage.renderingMode
设置的值如何,都不会应用色调。
如果你在UIImageView
的三个(或所有)边上有一个“最近邻居间距”约束,那么如果UIImage.renderingMode
设置为.alwaysTemplate
,则应用色调。
在纯粹的Storyboard / Interface Builder方法中,您可以通过将图像添加到资产目录,然后将图像集的“渲染为”属性更改为“模板图像”来设置图像的UIImage.renderingMode
。
尝试以编程方式设置tintColor
;它解决了我的问题。
我认为UIImageView中存在一个错误。如果在故事板中设置了色调,即使资源设置为渲染为模板,它也不会应用该色调。
解决方法是将色调颜色应用于故事板中的UIImageView父视图。
或者,将tintColor设置为nil,然后通过将UIImageView绑定到插座再将其设置为代码。
使用此扩展从界面构建器设置UIImageView tintColor。
extension UIImageView {
@IBInspectable var imageColor: UIColor! {
set {
super.tintColor = newValue
}
get {
return super.tintColor
}
}
}
通过删除我现有的UIImageView并添加一个新的问题,我的问题就消失了。显然,情况是你应该在将图像添加到Assets文件夹后添加UIImageView。
运行时属性技巧对我不起作用。我做这个课只是为了修理这种东西。您只需将所有有问题的图像视图设置为此类。
final class TintedImageView: UIImageView {
// WORKAROUND: Template images are not tinted when set using the Interface Builder.
override func layoutSubviews() {
super.layoutSubviews()
let preferredTintColor = tintColor
tintColor = nil
tintColor = preferredTintColor
}
}