[Swift] 進捗インジケーター付きのボタン

iOS

データの読み込みなどで使用できる、くるくる回る進捗インジケータ付きのボタンの紹介です。

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 //読み込み完了時にボタンを元に戻す
		}
	}

タイトルとURLをコピーしました