这个问题是关于Swift 4,Xcode 9.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
}
}
单击每个图标会在输出窗口(oneButton
,twoButton
,threeButton
)中显示相应的文本,具体取决于单击的文本。这很好。
当应用程序启动时,第一个图像的颜色为黑色(默认),如预期的那样。
单击twoButton
会使第一张图像上的颜色变为蓝色,如预期的那样。
单击threeButton
会使第一张图像上的颜色变为紫色,如预期的那样。
单击oneButton
会使第一张图像上的颜色重置为默认值(黑色)。这是 NOT 预期。
我想现在发生的事情是,由于按钮当前正在处理系统事件(触摸),因此某些系统进程会消除颜色设置。
我更改了代码,而不是Touch Up Inside
,myAction()
被调用Touch Down
,第一张图片DID的颜色变为红色!但只有在触摸时......一旦我发布,颜色就会恢复到默认状态。
我想要的是能够触摸oneButton
并将其更改为代码中的任何颜色,并保持这种状态,而不是将其重置为默认颜色。
上面的代码确实反复设置了图像渲染模式。我意识到,不应该这样做是必要的。但是当我没有这样做时,当应用程序在模拟器中运行时,不会改变任何颜色。上面的代码至少会改变图像的颜色,只要它不是被触摸的项目。在下面的代码中,虽然myAction()
中if / else的相应部分运行,但设置.tintColor
完全没有效果,无论点击哪个项目。我尝试使用experiment
真假,但无济于事。
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
}
}
答案 0 :(得分:1)
您无需反复设置图像,只需将图像设置为模板一次,稍后更改色调颜色即可。此外,使用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
}
答案 1 :(得分:0)
简短的回答是,您希望应用颜色的图像需要指定为模板图像。如果在图像资源的属性检查器中进行此指定,则原始问题中的所有代码都将起作用。任何对.withRenderingMode(.alwaysTemplate)
的调用都将变得不必要。
除非图像设置为模板图像,否则颜色不会被应用。
当前的工作方式(Xcode 9.4,Swift 4.1)是通过在GUI Attributes Inspector中将图像设置为模板图像。
完成此操作后,原始编辑问题中所有版本的代码都应按预期工作。
在代码中将图像设置为模板图像似乎应该工作,但是,至少对于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)
}