Skip to content

Instantly share code, notes, and snippets.

@ahmdmau
Created February 18, 2021 13:47
Show Gist options
  • Save ahmdmau/ab65503299ddb49e12829ee758e1e225 to your computer and use it in GitHub Desktop.
Save ahmdmau/ab65503299ddb49e12829ee758e1e225 to your computer and use it in GitHub Desktop.
Custom loading button with custom state with FLAnimatedImage (for showing gif data)
import UIKit
import FLAnimatedImage
@IBDesignable
open class LoadingButton: UIButton {
// MARK: - General Properties
public enum State: Int {
case initial
case loading
case finished
}
@IBInspectable open var imageAlpha: CGFloat = 1.0 {
didSet {
if let imageView = imageView {
imageView.alpha = imageAlpha
}
}
}
@IBInspectable var borderColorStart: UIColor = .aloMediumBlue
@IBInspectable var borderColorFinished: UIColor = .aloGreyishTwo
@IBInspectable var startText: String = "Default"
@IBInspectable var finishedText: String = "Default"
@IBInspectable var textColorStart: UIColor = .aloMediumBlue
@IBInspectable var textColorFinished: UIColor = .aloGreyishTwo
@IBInspectable var gifData: String = "icon-loading-blue"
@IBInspectable var initialImage: UIImage? {
didSet {
self.imageView?.image = initialImage
}
}
@IBInspectable var finishedImage: UIImage?
private var stateButton: State = .initial
lazy private var activityIndicator: FLAnimatedImageView = {
let imageView = FLAnimatedImageView()
return imageView
}()
private var action: (() -> Void)?
// MARK: - Lifecycle
open override func awakeFromNib() {
super.awakeFromNib()
setupActivityIndicator()
self.addTarget(self, action: #selector(tapped), for: .touchUpInside)
}
override open func layoutSubviews() {
super.layoutSubviews()
switch stateButton {
case .initial:
setInitialView()
break
case .loading:
setLoadingView()
break
case .finished:
setFinishedView()
break
}
self.imageView?.alpha = imageAlpha
}
// MARK: - Methods
open func touchUpInside(action: (() -> Void)? = nil) {
self.action = action
}
func setState(state: State) {
stateButton = state
self.setNeedsLayout()
}
@objc func tapped(sender: LoadingButton) {
self.action?()
}
private func setInitialView() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.isUserInteractionEnabled = true
UIView.animate(withDuration: 0.3, animations: { [weak self] in
guard let self = self else { return }
self.activityIndicator.alpha = 0.0
self.titleLabel?.alpha = 1.0
self.imageAlpha = 1
self.setTitle(self.startText, for: .normal)
self.setTitleColor(self.textColorStart, for: .normal)
self.setImage(self.initialImage, for: .normal)
self.layer.borderColor = self.borderColorStart.cgColor
})
}
}
private func setLoadingView() {
self.isUserInteractionEnabled = false
UIView.animate(withDuration: 0.3, animations: { [weak self] in
guard let self = self else { return }
self.titleLabel?.alpha = 0.0
self.imageAlpha = 0.0
self.activityIndicator.alpha = 1.0
self.layer.borderColor = self.borderColorStart.cgColor
})
}
private func setFinishedView() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.isUserInteractionEnabled = true
UIView.animate(withDuration: 0.3, animations: { [weak self] in
guard let self = self else { return }
self.activityIndicator.alpha = 0.0
self.titleLabel?.alpha = 1.0
self.imageAlpha = 1
self.setTitle(self.finishedText, for: .normal)
self.setTitleColor(self.textColorFinished, for: .normal)
self.setImage(self.finishedImage, for: .normal)
self.layer.borderColor = self.borderColorFinished.cgColor
})
}
}
private func setupActivityIndicator() {
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(activityIndicator)
activityIndicator.setCenterXYWithSuperview()
activityIndicator.setWidth(29)
activityIndicator.setHeight(29)
activityIndicator.animatedImage = FLAnimatedImage(gifResource: gifData)
activityIndicator.alpha = 0.0
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment