2016-04-11 17 views
8

Vorrei modificare il contenuto di un UIButton in ActivityIndicator dopo che è stato premuto.Indicatore di attività di visualizzazione all'interno di UIButton

So che i pulsanti hanno un imageView e un titleLabel, ma non so come inserire un indicatore di attività in nessuno di essi.

Questo è come mi creo indicatori di attività:

let aiView = UIActivityIndicatorView(activityIndicatorStyle: .Gray) 
aiView.startAnimating() 
aiView.center = CGPointMake(0,0) 
aiView.hidesWhenStopped = false 

risposta

12

codice trovato qui:

https://www.snip2code.com/Snippet/777050/iOS---Swift---UIButton-subclass-for-show/

import UIKit 

class LoadingButton: UIButton { 

    var originalButtonText: String? 
    var activityIndicator: UIActivityIndicatorView! 

    func showLoading() { 
     originalButtonText = self.titleLabel?.text 
     self.setTitle("", forState: UIControlState.Normal) 

     if (activityIndicator == nil) { 
      activityIndicator = createActivityIndicator() 
     } 

     showSpinning() 
    } 

    func hideLoading() { 
     self.setTitle(originalButtonText, forState: UIControlState.Normal) 
     activityIndicator.stopAnimating() 
    } 

    private func createActivityIndicator() -> UIActivityIndicatorView { 
     let activityIndicator = UIActivityIndicatorView() 
     activityIndicator.hidesWhenStopped = true 
     activityIndicator.color = UIColor.lightGrayColor() 
     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) 
    } 

} 
+0

pulito e semplice, grazie! – clemkoa

+0

Per un utilizzo di base che sembra fantastico. +1 –

1

Aggiornato risposta selezionata (steve-Rosenberg) per Apple Swift versione 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1) Xcode 8.1 (8B62)

import ObjectiveC 

private var originalButtonText: String? 
private var activityIndicator: UIActivityIndicatorView! 

extension UIButton{ 

    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 = UIColor.lightGray 
     return activityIndicator 
    } 

    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) 
    } 
} 
12

@Boris: questo non dovrebbe essere in un'estensione.

Qui è in swift 3, con codice migliorato: disabilita il pulsante, funziona con immagini e titoli.

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 
    } 

} 
+0

fyi, se hai un pulsante nello storyboard dovresti cambiare il suo tipo all'interno dell'ispettore identità non solo nel codice. – user1883993

0

eccellente @Steve,

Può usare sotto implementazione anziché la linea,

var activityIndicator: UIActivityIndicatorView!

utilizzare questo, in modo che se configuriamo l'indicatore di attività prima di chiamare showLoading(), l'applicazione non si bloccherà.

private var _activityIndicator:UIActivityIndicatorView! = nil 
var activityIndicator: UIActivityIndicatorView{ 
    set{ 
     _activityIndicator = newValue 

    } 
    get{ 
     if _activityIndicator == nil{ 
      _activityIndicator = createActivityIndicator() 
     } 
     return _activityIndicator 
    } 
} 
3

Swift 4.0 con una piccola modifica

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) 
    } 

}