iOS 13 `withTintColor` 不服从我指定的颜色
iOS 13 `withTintColor` not obeying the color I assign
我发现新 iOS 13 UIImage 属性 withTintColor(_:renderingMode:)
的行为令人费解。它有什么用,它与图像出现的上下文的色调颜色有什么关系?
例如:
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
iv.frame.origin = CGPoint(x: 100, y: 400)
self.view.addSubview(iv)
我说.red
。但它是蓝色的:
显然它是蓝色的,因为它的颜色来自周围环境的色调。但是,给图像 本身 着色有什么意义呢?
但它变得更奇怪了。我将绘制自己的图像并为 它 着色:
let sz = CGSize(width: 20, height: 20)
let im = UIGraphicsImageRenderer(size:sz).image { ctx in
ctx.cgContext.fillEllipse(in:CGRect(origin:.zero, size:sz))
}.withTintColor(.red)
let iv = UIImageView(image:im)
iv.frame.origin = CGPoint(x: 100, y: 400)
self.view.addSubview(iv)
我说 .red
是红色的:
不一致的原因是什么?
withTintColor
可能主要用于符号图像,它们始终被视为模板并且没有自己的颜色。不过,能把一张普通的图片当作模板,给它上色也是很不错的。
假设您正在自定义 UIView 的 draw(_:)
方法中绘图,或者在 UIImageView 图形上下文中绘图。模板视图一直存在问题;您在这里无法访问它们的模板行为,因此无法对它们进行着色。 withTintColor
解决了这个问题。
然而,毫无疑问,当您以任何其他方式使用这些方法时,它们的行为会非常奇怪:
只要您说 withTintColor
,生成的图像就会被 视为模板图像, 即使您说 .alwaysOriginal
.所以你的渲染模式现在被忽略了!
此外,在已经有 tintColor
的上下文中,现在可以有 两个相互竞争的 色调颜色:上下文的颜色(周围视图或继承的 tintColor
) 以及当您说 withTintColor
时图像的视图。如果这是 template 图像 — 符号图像,或 .alwaysTemplate
图像,或模板上下文中的图像,如按钮 — 那么 context 的 tintColor
获胜,您通过说 withTintColor
专门应用 的颜色将被忽略!!
例如,即使您专门将符号图像的色调颜色设置为红色,这也会产生蓝色符号图像(因为默认图像视图 tintColor
是蓝色):
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
要获得红色符号图像,您必须这样说:
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red,
renderingMode: .alwaysOriginal)
所以在第一个代码中,您指定的色调颜色被忽略(我们得到蓝色,而不是红色),但是在第二个代码中,您指定的渲染模式被忽略(它仍然是一个模板图像,但是现在它是红色的)。奇怪吧?
(我很难相信这是预期的行为,我已经提交了一个错误,但到目前为止 Apple 没有任何回应。)
我发现新 iOS 13 UIImage 属性 withTintColor(_:renderingMode:)
的行为令人费解。它有什么用,它与图像出现的上下文的色调颜色有什么关系?
例如:
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
iv.frame.origin = CGPoint(x: 100, y: 400)
self.view.addSubview(iv)
我说.red
。但它是蓝色的:
显然它是蓝色的,因为它的颜色来自周围环境的色调。但是,给图像 本身 着色有什么意义呢?
但它变得更奇怪了。我将绘制自己的图像并为 它 着色:
let sz = CGSize(width: 20, height: 20)
let im = UIGraphicsImageRenderer(size:sz).image { ctx in
ctx.cgContext.fillEllipse(in:CGRect(origin:.zero, size:sz))
}.withTintColor(.red)
let iv = UIImageView(image:im)
iv.frame.origin = CGPoint(x: 100, y: 400)
self.view.addSubview(iv)
我说 .red
是红色的:
不一致的原因是什么?
withTintColor
可能主要用于符号图像,它们始终被视为模板并且没有自己的颜色。不过,能把一张普通的图片当作模板,给它上色也是很不错的。
假设您正在自定义 UIView 的 draw(_:)
方法中绘图,或者在 UIImageView 图形上下文中绘图。模板视图一直存在问题;您在这里无法访问它们的模板行为,因此无法对它们进行着色。 withTintColor
解决了这个问题。
然而,毫无疑问,当您以任何其他方式使用这些方法时,它们的行为会非常奇怪:
只要您说
withTintColor
,生成的图像就会被 视为模板图像, 即使您说.alwaysOriginal
.所以你的渲染模式现在被忽略了!此外,在已经有
tintColor
的上下文中,现在可以有 两个相互竞争的 色调颜色:上下文的颜色(周围视图或继承的tintColor
) 以及当您说withTintColor
时图像的视图。如果这是 template 图像 — 符号图像,或.alwaysTemplate
图像,或模板上下文中的图像,如按钮 — 那么 context 的tintColor
获胜,您通过说withTintColor
专门应用 的颜色将被忽略!!
例如,即使您专门将符号图像的色调颜色设置为红色,这也会产生蓝色符号图像(因为默认图像视图 tintColor
是蓝色):
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red)
let iv = UIImageView(image:im)
要获得红色符号图像,您必须这样说:
let im = UIImage(systemName:"circle.fill")?.withTintColor(.red,
renderingMode: .alwaysOriginal)
所以在第一个代码中,您指定的色调颜色被忽略(我们得到蓝色,而不是红色),但是在第二个代码中,您指定的渲染模式被忽略(它仍然是一个模板图像,但是现在它是红色的)。奇怪吧?
(我很难相信这是预期的行为,我已经提交了一个错误,但到目前为止 Apple 没有任何回应。)