如何防止 UIButton 的图像颜色重置为默认值?
How can I keep the image color of UIButton from resetting to default?
这个问题是关于Swift4,Xcode9.3.1.
更改图像按钮颜色的过程有详细记录。这不是问题。
这个问题是关于 如果按钮恰好是 IBAction
中的目标,为什么图像按钮的颜色会重置为默认颜色,以及如何处理关于它。
我在 Xcode 中创建了一个新项目来演示我所看到的。这是一个在视图控制器中有一个 IBAction 的项目,它试图改变按钮上图像的颜色。我在应用程序中添加了三个按钮(oneButton
、twoButton
、threeButton
),并连接了它们,因此每个按钮都有以下插座:
每个按钮都定义了不同的图像。这是一个例子:
这里是 ViewController
:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var oneButton: UIButton!
@IBOutlet weak var twoButton: UIButton!
@IBOutlet weak var threeButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func myAction(sender: UIButton) {
let oneImageView = oneButton.imageView
if sender == oneButton {
print("oneButton")
oneImageView?.setImageColor(color: UIColor.red)
} else if sender == twoButton {
print("twoButton")
oneImageView?.setImageColor(color: UIColor.blue)
} else if sender == threeButton {
print("threeButton")
oneImageView?.setImageColor(color: UIColor.purple)
}
}
}
extension UIImageView {
func setImageColor(color: UIColor) {
let templateImage = self.image?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
self.image = templateImage
self.tintColor = color
}
}
单击每个图标会在输出 window(oneButton
、twoButton
、threeButton
)中显示相应的文本,具体取决于单击的是哪个图标。效果不错。
当应用程序启动时,第一张图片的颜色是黑色(默认),正如预期的那样。
单击 twoButton
会使第一张图片的颜色按预期变为蓝色。
单击 threeButton
会使第一张图片的颜色按预期变为紫色。
单击 oneButton
会使第一个图像的颜色重置为默认值(黑色)。这是 不 预期的。
我想这是怎么回事,因为按钮当前正在处理系统事件(触摸),所以我设置的颜色被某些系统进程擦掉了。
我更改了代码,因此在 Touch Down
上调用了 myAction()
而不是 Touch Up Inside
,第一张图片的颜色确实变成了红色!但是只有在触摸的时候……一松开,颜色就恢复默认了。
我想要的是能够触摸 oneButton
并将其更改为代码中的任何颜色,并保持这种状态,而不是将其重置为默认颜色。
添加/编辑
上面的代码确实一遍又一遍地设置图像渲染模式。我意识到,不应该 这样做。但是当我不这样做时,在模拟器中应用程序 运行 时不会更改任何颜色。只要不是被触摸的项目,上面的代码至少会改变图像的颜色。在下面的代码中,尽管 myAction()
中 if/else 的适当部分运行,设置 .tintColor
根本没有效果,无论单击哪个项目。我尝试了 experiment
true 和 false,但无济于事。
class ViewController: UIViewController {
@IBOutlet weak var oneButton: UIButton!
@IBOutlet weak var twoButton: UIButton!
@IBOutlet weak var threeButton: UIButton!
var oneImageView: UIImageView!
var oneImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
oneImageView = oneButton.imageView
oneImage = oneImageView?.image
let experiment = true
if experiment {
oneImageView?.image = UIImage(named: "image")?.withRenderingMode(.alwaysTemplate)
} else {
oneImage.withRenderingMode(.alwaysTemplate)
oneImageView.image = oneImage
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func myAction(sender: UIButton) {
//let oneImageView = oneButton.imageView
let tintColor: UIColor = {
print("switch doesn't work here for some reason")
if sender == oneButton {
print("oneButton")
return .red
} else if sender == twoButton {
print("twoButton")
return .blue
} else if sender == threeButton {
print("threeButton")
return .purple
} else {
return .cyan
}
}()
oneImageView?.tintColor = tintColor
}
}
您无需反复设置图片,只需将图片设置一次作为模板,稍后更改色调即可。此外,使用 switch
而不是多个 if
更简洁。
override func viewDidLoad() {
super.viewDidLoad()
oneImageView?.image = UIImage(named: "image").withRenderingMode(.alwaysTemplate)
}
@IBAction func myAction(_ sender: UIButton) {
let tintColor: UIColor = {
switch sender {
case oneButton: return .red
case twoButton: return .blue
case threeButton: return .purple
default: return .clear
}
}()
oneImageView?.tintColor = tintColor
}
设置模板图片
简短的回答是,您希望应用颜色的图像需要指定为模板图像。如果在图像资产的属性检查器中进行此指定,则原始问题中的所有代码都将起作用。对 .withRenderingMode(.alwaysTemplate)
的任何调用都将变得不必要。
在属性检查器中
除非图像设置为 模板图像,否则不会应用颜色。
当前 的工作方式(Xcode 9.4,Swift 4.1)是在 GUI 属性检查器中将图像设置为模板图像。
完成此操作后,原始问题和编辑过的问题中的所有代码版本都应按预期工作。
在代码中
在代码中将图像设置为模板图像似乎应该有效,但是,至少在 Xcode 9.4、Swift 4.1 上一个模拟器,它没有永久性;第一次用户触摸重置它。
在下面的代码中,.withRenderingMode(.alwaysTemplate)
确实使图标变成了模板,但是 一旦用户第一次触摸图标,它就会再次变成默认呈现。 在模拟中是这样iPhone(没有在物理设备上测试)
override func viewDidLoad() {
super.viewDidLoad()
oneImageView = oneButton.imageView
// NOT PERMANENT
oneImageView?.image = UIImage(named: "image")?.withRenderingMode(.alwaysTemplate)
}
这个问题是关于Swift4,Xcode9.3.1.
更改图像按钮颜色的过程有详细记录。这不是问题。
这个问题是关于 如果按钮恰好是 IBAction
中的目标,为什么图像按钮的颜色会重置为默认颜色,以及如何处理关于它。
我在 Xcode 中创建了一个新项目来演示我所看到的。这是一个在视图控制器中有一个 IBAction 的项目,它试图改变按钮上图像的颜色。我在应用程序中添加了三个按钮(oneButton
、twoButton
、threeButton
),并连接了它们,因此每个按钮都有以下插座:
每个按钮都定义了不同的图像。这是一个例子:
这里是 ViewController
:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var oneButton: UIButton!
@IBOutlet weak var twoButton: UIButton!
@IBOutlet weak var threeButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func myAction(sender: UIButton) {
let oneImageView = oneButton.imageView
if sender == oneButton {
print("oneButton")
oneImageView?.setImageColor(color: UIColor.red)
} else if sender == twoButton {
print("twoButton")
oneImageView?.setImageColor(color: UIColor.blue)
} else if sender == threeButton {
print("threeButton")
oneImageView?.setImageColor(color: UIColor.purple)
}
}
}
extension UIImageView {
func setImageColor(color: UIColor) {
let templateImage = self.image?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
self.image = templateImage
self.tintColor = color
}
}
单击每个图标会在输出 window(oneButton
、twoButton
、threeButton
)中显示相应的文本,具体取决于单击的是哪个图标。效果不错。
当应用程序启动时,第一张图片的颜色是黑色(默认),正如预期的那样。
单击 twoButton
会使第一张图片的颜色按预期变为蓝色。
单击 threeButton
会使第一张图片的颜色按预期变为紫色。
单击 oneButton
会使第一个图像的颜色重置为默认值(黑色)。这是 不 预期的。
我想这是怎么回事,因为按钮当前正在处理系统事件(触摸),所以我设置的颜色被某些系统进程擦掉了。
我更改了代码,因此在 Touch Down
上调用了 myAction()
而不是 Touch Up Inside
,第一张图片的颜色确实变成了红色!但是只有在触摸的时候……一松开,颜色就恢复默认了。
我想要的是能够触摸 oneButton
并将其更改为代码中的任何颜色,并保持这种状态,而不是将其重置为默认颜色。
添加/编辑
上面的代码确实一遍又一遍地设置图像渲染模式。我意识到,不应该 这样做。但是当我不这样做时,在模拟器中应用程序 运行 时不会更改任何颜色。只要不是被触摸的项目,上面的代码至少会改变图像的颜色。在下面的代码中,尽管 myAction()
中 if/else 的适当部分运行,设置 .tintColor
根本没有效果,无论单击哪个项目。我尝试了 experiment
true 和 false,但无济于事。
class ViewController: UIViewController {
@IBOutlet weak var oneButton: UIButton!
@IBOutlet weak var twoButton: UIButton!
@IBOutlet weak var threeButton: UIButton!
var oneImageView: UIImageView!
var oneImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
oneImageView = oneButton.imageView
oneImage = oneImageView?.image
let experiment = true
if experiment {
oneImageView?.image = UIImage(named: "image")?.withRenderingMode(.alwaysTemplate)
} else {
oneImage.withRenderingMode(.alwaysTemplate)
oneImageView.image = oneImage
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func myAction(sender: UIButton) {
//let oneImageView = oneButton.imageView
let tintColor: UIColor = {
print("switch doesn't work here for some reason")
if sender == oneButton {
print("oneButton")
return .red
} else if sender == twoButton {
print("twoButton")
return .blue
} else if sender == threeButton {
print("threeButton")
return .purple
} else {
return .cyan
}
}()
oneImageView?.tintColor = tintColor
}
}
您无需反复设置图片,只需将图片设置一次作为模板,稍后更改色调即可。此外,使用 switch
而不是多个 if
更简洁。
override func viewDidLoad() {
super.viewDidLoad()
oneImageView?.image = UIImage(named: "image").withRenderingMode(.alwaysTemplate)
}
@IBAction func myAction(_ sender: UIButton) {
let tintColor: UIColor = {
switch sender {
case oneButton: return .red
case twoButton: return .blue
case threeButton: return .purple
default: return .clear
}
}()
oneImageView?.tintColor = tintColor
}
设置模板图片
简短的回答是,您希望应用颜色的图像需要指定为模板图像。如果在图像资产的属性检查器中进行此指定,则原始问题中的所有代码都将起作用。对 .withRenderingMode(.alwaysTemplate)
的任何调用都将变得不必要。
在属性检查器中
除非图像设置为 模板图像,否则不会应用颜色。
当前 的工作方式(Xcode 9.4,Swift 4.1)是在 GUI 属性检查器中将图像设置为模板图像。
完成此操作后,原始问题和编辑过的问题中的所有代码版本都应按预期工作。
在代码中
在代码中将图像设置为模板图像似乎应该有效,但是,至少在 Xcode 9.4、Swift 4.1 上一个模拟器,它没有永久性;第一次用户触摸重置它。
在下面的代码中,.withRenderingMode(.alwaysTemplate)
确实使图标变成了模板,但是 一旦用户第一次触摸图标,它就会再次变成默认呈现。 在模拟中是这样iPhone(没有在物理设备上测试)
override func viewDidLoad() {
super.viewDidLoad()
oneImageView = oneButton.imageView
// NOT PERMANENT
oneImageView?.image = UIImage(named: "image")?.withRenderingMode(.alwaysTemplate)
}