はじめに
こんにちは。
色をフェードアニメーションして変更する時に少し悩んだので書いてみました。
簡単なアニメーションをする場合、以下のようなメソッドを利用すると思います。
UIView.animate(withDuration: 0.5, delay: 0, animations: { [unowned self] Void in
//処理
})
アプリ制作にあたり、UIButtonやUISwitch,UINavigationBarなどの
backgroundColorやtintColorをアニメーションをしながら変更したいと思ったのですが、一部の部品で正常にフェードアニメーションをせず、すぐに色が変わってしまうことがあったので少し調べてみました。
至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。
UI部品一覧(主に変更するプロパティを書いてみました)
部品名 | 正常にフェードアニメーションする | 正常にフェードアニメーションしない |
---|---|---|
UINavigationBar | - | barTintColor,※titleTextColor |
UIView | backgroundColor | - |
UIButton | backgroundColor,tintColor | - |
UISwitch | backgroundColor | onTintColor |
UILabel | - | backgroundColor,textColor |
UISegmentedControl | tintColor | - |
解決するためのExtensionを書いてみる
正常にアニメーションしないプロパティに対してExtensionで対応してみたいと思います。
関数名などは、ご自由に変更してください。
UINavigationBar
※titleTextColorという計算型プロパティを追加しています※
extension UINavigationBar {
func setBarTintColor(_ color: UIColor, duration: TimeInterval = 0, option: UIViewAnimationOptions = [], completion:(()->())? = nil) {
var setting: UIViewAnimationOptions = option
setting.insert(UIViewAnimationOptions.transitionCrossDissolve)
UIView.transition(with: self, duration: duration, options: setting, animations: {
self.barTintColor = color
}) { (finish) in
if finish { completion?() }
}
}
func setTitleTextColor(_ color: UIColor, duration: TimeInterval = 0, option: UIViewAnimationOptions = [], completion:(()->())? = nil) {
var setting: UIViewAnimationOptions = option
setting.insert(UIViewAnimationOptions.transitionCrossDissolve)
UIView.transition(with: self, duration: duration, options: setting, animations: {
self.titleTextColor = color
}) { (finish) in
if finish { completion?() }
}
}
//バーのタイトルの文字の色を変更できます
var titleTextColor: UIColor {
get {
let color = titleTextAttributes?[NSForegroundColorAttributeName] as! UIColor
return color
}
set {
titleTextAttributes = [NSForegroundColorAttributeName : newValue]
}
}
}
UISwitch
extension UISwitch {
func setOnTintColor(_ color: UIColor, duration: TimeInterval = 0, option: UIViewAnimationOptions = [], completion:(()->())? = nil) {
var setting: UIViewAnimationOptions = option
setting.insert(UIViewAnimationOptions.transitionCrossDissolve)
if !isOn {
self.onTintColor = color
return
}
UIView.transition(with: self, duration: duration, options: setting, animations: {
self.onTintColor = color
}) { (finish) in
if finish { completion?() }
}
}
}
UILabel
extension UILabel {
func setBackgroundColor(_ color: UIColor, duration: TimeInterval = 0, option: UIViewAnimationOptions = [], completion:(()->())? = nil) {
var setting: UIViewAnimationOptions = option
setting.insert(UIViewAnimationOptions.transitionCrossDissolve)
UIView.transition(with: self, duration: duration, options: setting, animations: {
self.backgroundColor = color
}) { (finish) in
if finish { completion?() }
}
}
func setTextColor(_ color: UIColor, duration: TimeInterval = 0, option: UIViewAnimationOptions = [], completion:(()->())? = nil) {
var setting: UIViewAnimationOptions = option
setting.insert(UIViewAnimationOptions.transitionCrossDissolve)
UIView.transition(with: self, duration: duration, options: setting, animations: {
self.textColor = color
}) { (finish) in
if finish { completion?() }
}
}
}
サンプルコード
無事にアニメーションをしてくれたようです。
import UIKit
class MainViewController: UIViewController {
@IBOutlet weak var navigationBar: UINavigationBar!
@IBOutlet weak var uiView: UIView!
@IBOutlet weak var button: UIButton!
@IBOutlet weak var uiSwitch: UISwitch!
@IBOutlet weak var label: UILabel!
@IBOutlet weak var segmentedControl: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func blueAction(_ sender: Any) {
let color = UIColor(hex: 0xbce7fe)
UIView.animate(withDuration: 0.5, delay: 0, animations: { [unowned self] Void in
// self.navigationBar.barTintColor = color
self.uiView.backgroundColor = color
self.button.backgroundColor = color
// self.uiSwitch.onTintColor = color
// self.label.backgroundColor = color
self.segmentedControl.tintColor = color
})
navigationBar.setBarTintColor(color, duration: 0.5)
uiSwitch.setOnTintColor(color, duration: 0.5)
label.setBackgroundColor(color, duration: 0.5)
}
@IBAction func greenAction(_ sender: Any) {
let color = UIColor(hex: 0xa7e040)
UIView.animate(withDuration: 0.5, delay: 0, animations: { [unowned self] Void in
// self.navigationBar.barTintColor = color
self.uiView.backgroundColor = color
self.button.backgroundColor = color
// self.uiSwitch.onTintColor = color
// self.label.backgroundColor = color
self.segmentedControl.tintColor = color
})
navigationBar.setBarTintColor(color, duration: 0.5)
uiSwitch.setOnTintColor(color, duration: 0.5)
label.setBackgroundColor(color, duration: 0.5)
}
}
参考にさせていただいた記事
iOSアニメーションについて
UIView animateについて
見て頂いてありがとうございます。