データの読み込みなどで使用できる、くるくる回る進捗インジケータ付きのボタンの紹介です。
Storyboard・コードどちらからでも使用可能です。
UIButtonカスタムクラス
import UIKit
final class ButtonWithLoad: UIButton {
fileprivate var viewIndicator: UIActivityIndicatorView!
override init(frame: CGRect) {
super.init(frame: frame)
addIndicatorView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
addIndicatorView()
}
fileprivate func addIndicatorView() {
if #available(iOS 13.0, *) {
viewIndicator = UIActivityIndicatorView(style: .medium)
viewIndicator.color = UIColor.white
} else {
viewIndicator = UIActivityIndicatorView(style: .white)
}
self.addSubview(viewIndicator)
//インジケーターをAutoLayoutでボタン中央に配置
viewIndicator.translatesAutoresizingMaskIntoConstraints = false
viewIndicator.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
viewIndicator.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
}
var isLoading: Bool = false {
didSet {
self.isEnabled = !isLoading //ロード中はボタンを無効にする
self.titleLabel?.isHidden = isLoading
if isLoading {
viewIndicator.startAnimating()
self.titleLabel?.removeFromSuperview()
} else {
viewIndicator.stopAnimating()
if let label = self.titleLabel {
self.addSubview(label)
}
}
}
}
}
使い方
Storyboardから使用する場合
UIButtonを配置し、Custom Classに「ButtonWithLoad」を設定します。
コントローラーにタップ時のイベントを追加します。
@IBAction fileprivate func onTouchLoad(_ sender: ButtonWithLoad) {
sender.isLoading = true //読み込み開始
//読み込み処理など
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
sender.isLoading = false //読み込み完了時にボタンを元に戻す
}
}
コードから使用する場合
override func viewDidLoad() {
super.viewDidLoad()
//ボタンを配置
let button = ButtonWithLoad(frame: CGRect(x: 100, y: 100, width: 120, height: 44))
button.setTitle("読み込み開始", for: .normal)
button.backgroundColor = .blue
button.setTitleColor(.white, for: .normal)
//タップ時のイベントを追加
button.addTarget(self, action: #selector(self.onTouchLoad(_:)), for: .touchUpInside)
self.view.addSubview(button)
}
@objc fileprivate func onTouchLoad(_ sender: ButtonWithLoad) {
sender.isLoading = true //読み込み開始
//読み込み処理など
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
sender.isLoading = false //読み込み完了時にボタンを元に戻す
}
}