2016-04-11 22 views
8

Chciałbym zmienić zawartość UIButton na ActivityIndicator po jego naciśnięciu.Wskaźnik aktywności wyświetlania wewnątrz UIButton

Wiem, że przyciski mają imageView i titleLabel, ale nie wiem jak umieścić wskaźnik aktywności w żadnym z nich.

ten sposób tworzę wskaźniki aktywności:

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

Odpowiedz

12

Kod znaleźć tutaj:

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

Czyste i proste, dzięki! – clemkoa

+0

Do podstawowego użytku, który wygląda świetnie. +1 –

1

Updated wybrana odpowiedź (steve-Rosenberg) dla Apple Swift w wersji 3.0.1 (swiftlang-800.0.58,6 klang-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: To nie powinno być przedłużeniem.

Tutaj jest w szybkim 3, z ulepszonym kodem: wyłącza przycisk, działa z obrazami i tytułami.

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, jeśli masz przycisk w scenorysie, musisz zmienić jego typ w inspektorze tożsamości, nie tylko w kodzie. – user1883993

0

Doskonała @Steve,

można używać zamiast realizacji poniżej linii

var activityIndicator: UIActivityIndicatorView!

użyj tego, aby skonfigurować wskaźnik aktywności przed wywołaniem showLoading(), aplikacja się nie zawiesza.

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

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

Swift 4.0 z niewielką modyfikacją

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

} 
Powiązane problemy