前提・実現したいこと
iOSアプリを作っています。
ボタンアクションでオンにしたら(ボタン背景に)グラデーションの色がついて、オフにしたらグラデーションの色が消える(元に戻る)ようにしたいです。
グラデーションは以下のように設定し、
swift
1extension UIButton{ 2 3 func setGradient(color1: UIColor, color2: UIColor){ 4 let gradinetLayer = CAGradientLayer() 5 gradinetLayer.frame = bounds 6 gradinetLayer.colors = [color1.cgColor, color2.cgColor] 7 gradinetLayer.locations = [0.0, 0.9] 8 gradinetLayer.startPoint = CGPoint(x: 0.0, y: 1.0) 9 gradinetLayer.endPoint = CGPoint(x: 1.0, y: 1.0) 10 11 layer.insertSublayer(gradinetLayer, at: 0) 12 } 13}
使う場所で以下のようにしています。
swift
1@IBAction func tag1ButtonAction(_ sender: UIButton) { 2 3 sender.switchAction(onAction: { 4 self.tag1Button.setGradient(color1: .cyan, color2: .systemBlue) 5 self.tag1Button.setTitleColor(UIColor.white, for: .normal) 6 }) { 7 ※ここで戻るようにしたい 8 self.tag1Button.setTitleColor(UIColor.black, for: .normal) 9 } 10 } 11extension UIButton { 12 13 func switchAction(onAction: @escaping ()->Void, offAction: @escaping ()->Void) { 14 15 //選択状態を反転 16 self.isSelected = !self.isSelected 17 18 switch self.isSelected { 19 case true: 20 //ONにする時に走らせたい処理 21 onAction() 22 case false: 23 //OFFにする時に走らせたい処理 24 offAction() 25 } 26 27 } 28} 29
試したこと
「※ここで戻るようにしたい」の部分にself.tag1Button.backgroundColor = UIColor.white
としてもテキストカラーしか変わらず、self.tag1Button.setGradient(color1: .white, color2: .white)
としても同じで、XXXButton.layer.removeFromSuperlayer()
やXXXButton.layer.sublayers = nil
としたら、ボタン自体が消え去り、もう一度押すと(オン→オフ→オン)Thread 1: EXC_BAD_ACCESS (code=1, address=0x450c8fc1218)
のエラーが出てクラッシュします。
補足情報(FW/ツールのバージョンなど)
swift5
Xcode11
オンにした時に insertSublayer した gradinetLayer を覚えておいて、オフにした時に removeFromSuperlayer する必要があるのでは。
ありがとうございます。申し訳ございません。「覚えておく」とはどのようにすればよろしいでしょうか?ご教示願います。
ViewController のプロパティで。または、CAGradientLayer に名前をつけて、それで検索って手も。
すいません。何かが違うようです。
```
@IBAction func tag1ButtonAction(_ sender: UIButton) {
sender.switchAction(onAction: {
self.tag1Button.setGradient(color1: .cyan, color2: .systemBlue)
self.tag1Button.setTitleColor(UIColor.white, for: .normal)
}) {
let buttonGradient = CAGradientLayer()
buttonGradient.name = "Gradient"
// Removing
self.tag1Button.layer.sublayers?.first(where: { $0.name == "Gradient"})?.removeFromSuperlayer()
self.tag1Button.setTitleColor(UIColor.black, for: .normal)
}
}
```
これだと文字色だけが変わります。
「オンにした時に insertSublayer した gradinetLayer を覚えておいて、オフにした時に removeFromSuperlayer する」
をそのまま記述すれば実現できましたよ。
グラデーションをつけたレイヤーに名前をつけましょう。
上記のコードではそれができていません。
あなたの回答
tips
プレビュー