Display activity indicator inside UIButton Display activity indicator inside UIButton ios ios

Display activity indicator inside UIButton


import UIKitclass LoadingButton: UIButton {private var originalButtonText: String?var activityIndicator: UIActivityIndicatorView!func showLoading() {    originalButtonText = self.titleLabel?.text    self.setTitle("", for: .normal)        if (activityIndicator == nil) {        activityIndicator = createActivityIndicator()    }        showSpinning()}func hideLoading() {    self.setTitle(originalButtonText, for: .normal)    activityIndicator.stopAnimating()}private func createActivityIndicator() -> UIActivityIndicatorView {    let activityIndicator = UIActivityIndicatorView()    activityIndicator.hidesWhenStopped = true    activityIndicator.color = .lightGray    return activityIndicator}private func showSpinning() {    activityIndicator.translatesAutoresizingMaskIntoConstraints = false    self.addSubview(activityIndicator)    centerActivityIndicatorInButton()    activityIndicator.startAnimating()}private func centerActivityIndicatorInButton() {    let xCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: activityIndicator, attribute: .centerX, multiplier: 1, constant: 0)    self.addConstraint(xCenterConstraint)        let yCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: activityIndicator, attribute: .centerY, multiplier: 1, constant: 0)    self.addConstraint(yCenterConstraint)}}


@Boris: This should not be in an extension.

Here it is in swift 3/4, with improved code: disables button, works with images and titles.

class LoadingButton: UIButton {    struct ButtonState {        var state: UIControlState        var title: String?        var image: UIImage?    }    private (set) var buttonStates: [ButtonState] = []    private lazy var activityIndicator: UIActivityIndicatorView = {        let activityIndicator = UIActivityIndicatorView()        activityIndicator.hidesWhenStopped = true        activityIndicator.color = self.titleColor(for: .normal)        self.addSubview(activityIndicator)        activityIndicator.translatesAutoresizingMaskIntoConstraints = false        let xCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: activityIndicator, attribute: .centerX, multiplier: 1, constant: 0)        let yCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: activityIndicator, attribute: .centerY, multiplier: 1, constant: 0)        self.addConstraints([xCenterConstraint, yCenterConstraint])        return activityIndicator    }()    func showLoading() {        activityIndicator.startAnimating()        var buttonStates: [ButtonState] = []        for state in [UIControlState.disabled] {            let buttonState = ButtonState(state: state, title: title(for: state), image: image(for: state))            buttonStates.append(buttonState)            setTitle("", for: state)            setImage(UIImage(), for: state)        }        self.buttonStates = buttonStates        isEnabled = false    }    func hideLoading() {        activityIndicator.stopAnimating()        for buttonState in buttonStates {            setTitle(buttonState.title, for: buttonState.state)            setImage(buttonState.image, for: buttonState.state)        }        isEnabled = true    }}


Swift 4.0 with a little modification

class LoadingUIButton: UIButton {    @IBInspectable var indicatorColor : UIColor = .lightGray    var originalButtonText: String?    var activityIndicator: UIActivityIndicatorView!    func showLoading() {        originalButtonText = self.titleLabel?.text        self.setTitle("", for: .normal)        if (activityIndicator == nil) {            activityIndicator = createActivityIndicator()        }        showSpinning()    }    func hideLoading() {        DispatchQueue.main.async(execute: {            self.setTitle(self.originalButtonText, for: .normal)            self.activityIndicator.stopAnimating()        })    }    private func createActivityIndicator() -> UIActivityIndicatorView {        let activityIndicator = UIActivityIndicatorView()        activityIndicator.hidesWhenStopped = true        activityIndicator.color = indicatorColor        return activityIndicator    }    private func showSpinning() {        activityIndicator.translatesAutoresizingMaskIntoConstraints = false        self.addSubview(activityIndicator)        centerActivityIndicatorInButton()        activityIndicator.startAnimating()    }    private func centerActivityIndicatorInButton() {        let xCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: activityIndicator, attribute: .centerX, multiplier: 1, constant: 0)        self.addConstraint(xCenterConstraint)        let yCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: activityIndicator, attribute: .centerY, multiplier: 1, constant: 0)        self.addConstraint(yCenterConstraint)    }}