Quiero mostrar, mediante programación, un indicador de actividad con texto, como el de la aplicación Fotos (después de editar y guardar una imagen). ¿Cómo puedo hacer esto?
Quiero mostrar, mediante programación, un indicador de actividad con texto, como el de la aplicación Fotos (después de editar y guardar una imagen). ¿Cómo puedo hacer esto?
Respuestas:
Xcode 9.0 • Swift 4.0
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var filterButton: UIButton!
@IBOutlet weak var saveButton: UIButton!
let destinationUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
.appendingPathComponent("filteredImage.png")
let imagePicker = UIImagePickerController()
let messageFrame = UIView()
var activityIndicator = UIActivityIndicatorView()
var strLabel = UILabel()
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
func activityIndicator(_ title: String) {
strLabel.removeFromSuperview()
activityIndicator.removeFromSuperview()
effectView.removeFromSuperview()
strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 160, height: 46))
strLabel.text = title
strLabel.font = .systemFont(ofSize: 14, weight: .medium)
strLabel.textColor = UIColor(white: 0.9, alpha: 0.7)
effectView.frame = CGRect(x: view.frame.midX - strLabel.frame.width/2, y: view.frame.midY - strLabel.frame.height/2 , width: 160, height: 46)
effectView.layer.cornerRadius = 15
effectView.layer.masksToBounds = true
activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
activityIndicator.startAnimating()
effectView.contentView.addSubview(activityIndicator)
effectView.contentView.addSubview(strLabel)
view.addSubview(effectView)
}
func saveImage() {
do {
try imageView.image?.data?.write(to: destinationUrl, options: .atomic)
print("file saved")
} catch {
print(error)
}
}
func applyFilterToImage() {
imageView.image = imageView.image?.applying(contrast: 1.5)
}
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/a/a8/VST_images_the_Lagoon_Nebula.jpg"), let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return }
view.backgroundColor = UIColor(white: 0, alpha: 1)
imageView.image = image
}
@IBAction func startSavingImage(_ sender: AnyObject) {
saveButton.isEnabled = false
filterButton.isEnabled = false
activityIndicator("Saving Image")
DispatchQueue.main.async {
self.saveImage()
DispatchQueue.main.async {
self.effectView.removeFromSuperview()
self.saveButton.isEnabled = true
self.filterButton.isEnabled = true
}
}
}
@IBAction func filterAction(_ sender: AnyObject) {
filterButton.isEnabled = false
saveButton.isEnabled = false
activityIndicator("Applying Filter")
DispatchQueue.main.async {
self.applyFilterToImage()
DispatchQueue.main.async {
self.effectView.removeFromSuperview()
self.filterButton.isEnabled = true
self.saveButton.isEnabled = true
}
}
}
@IBAction func cameraAction(_ sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePicker.delegate = self
imagePicker.sourceType = .camera
present(imagePicker, animated: true)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [AnyHashable: Any]!) {
dismiss(animated: true, completion: nil)
imageView.image = image
}
}
extension Data {
var image: UIImage? { return UIImage(data: self) }
}
extension UIImage {
var data: Data? { return UIImagePNGRepresentation(self) }
func applying(contrast value: NSNumber) -> UIImage? {
guard let ciImage = CIImage(image: self)?.applyingFilter("CIColorControls", withInputParameters: [kCIInputContrastKey: value]) else { return nil }
UIGraphicsBeginImageContextWithOptions(size, false, scale)
defer { UIGraphicsEndImageContext() }
UIImage(ciImage: ciImage).draw(in: CGRect(origin: .zero, size: size))
return UIGraphicsGetImageFromCurrentImageContext()
}
}
removeFromSuperview
y configuré a nil
. ¡No estoy seguro de si es la mejor manera, pero su código establecido anteriormente ayudó mucho!
Si bien la respuesta de Esq funciona, agregué mi propia implementación, que está más en línea con una buena arquitectura de componentes al separar la vista en su propia clase. También utiliza el desenfoque dinámico introducido en iOS 8.
Así es como se ve el mío con un fondo de imagen:
El código para esto está encapsulado en su propia clase UIView, lo que significa que puede reutilizarlo cuando lo desee.
Uso
func viewDidLoad() {
super.viewDidLoad()
// Create and add the view to the screen.
let progressHUD = ProgressHUD(text: "Saving Photo")
self.view.addSubview(progressHUD)
// All done!
self.view.backgroundColor = UIColor.black
}
Código UIView
import UIKit
class ProgressHUD: UIVisualEffectView {
var text: String? {
didSet {
label.text = text
}
}
let activityIndictor: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
let label: UILabel = UILabel()
let blurEffect = UIBlurEffect(style: .light)
let vibrancyView: UIVisualEffectView
init(text: String) {
self.text = text
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
super.init(effect: blurEffect)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
self.text = ""
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
super.init(coder: aDecoder)
self.setup()
}
func setup() {
contentView.addSubview(vibrancyView)
contentView.addSubview(activityIndictor)
contentView.addSubview(label)
activityIndictor.startAnimating()
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superview = self.superview {
let width = superview.frame.size.width / 2.3
let height: CGFloat = 50.0
self.frame = CGRect(x: superview.frame.size.width / 2 - width / 2,
y: superview.frame.height / 2 - height / 2,
width: width,
height: height)
vibrancyView.frame = self.bounds
let activityIndicatorSize: CGFloat = 40
activityIndictor.frame = CGRect(x: 5,
y: height / 2 - activityIndicatorSize / 2,
width: activityIndicatorSize,
height: activityIndicatorSize)
layer.cornerRadius = 8.0
layer.masksToBounds = true
label.text = text
label.textAlignment = NSTextAlignment.center
label.frame = CGRect(x: activityIndicatorSize + 5,
y: 0,
width: width - activityIndicatorSize - 15,
height: height)
label.textColor = UIColor.gray
label.font = UIFont.boldSystemFont(ofSize: 16)
}
}
func show() {
self.isHidden = false
}
func hide() {
self.isHidden = true
}
}
Un ejemplo de cómo usarlo es así:
override func viewDidLoad() {
super.viewDidLoad()
// Create and add the view to the screen.
let progressHUD = ProgressHUD(text: "Saving Photo")
self.view.addSubview(progressHUD)
// All done!
self.view.backgroundColor = UIColor.blackColor()
}
Aquí está el código de UIView:
import UIKit
class ProgressHUD: UIVisualEffectView {
var text: String? {
didSet {
label.text = text
}
}
let activityIndictor: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
let label: UILabel = UILabel()
let blurEffect = UIBlurEffect(style: .Light)
let vibrancyView: UIVisualEffectView
init(text: String) {
self.text = text
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(effect: blurEffect)
self.setup()
}
required init(coder aDecoder: NSCoder) {
self.text = ""
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(coder: aDecoder)
self.setup()
}
func setup() {
contentView.addSubview(vibrancyView)
vibrancyView.contentView.addSubview(activityIndictor)
vibrancyView.contentView.addSubview(label)
activityIndictor.startAnimating()
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superview = self.superview {
let width = superview.frame.size.width / 2.3
let height: CGFloat = 50.0
self.frame = CGRectMake(superview.frame.size.width / 2 - width / 2,
superview.frame.height / 2 - height / 2,
width,
height)
vibrancyView.frame = self.bounds
let activityIndicatorSize: CGFloat = 40
activityIndictor.frame = CGRectMake(5, height / 2 - activityIndicatorSize / 2,
activityIndicatorSize,
activityIndicatorSize)
layer.cornerRadius = 8.0
layer.masksToBounds = true
label.text = text
label.textAlignment = NSTextAlignment.Center
label.frame = CGRectMake(activityIndicatorSize + 5, 0, width - activityIndicatorSize - 15, height)
label.textColor = UIColor.grayColor()
label.font = UIFont.boldSystemFontOfSize(16)
}
}
func show() {
self.hidden = false
}
func hide() {
self.hidden = true
}
}
Espero que esto ayude, no dude en usar este código donde lo necesite.
label.color = <color>
se ignora: -S
label.textColor = UIColor.greenColor()
, no afectará al color del texto.
Así es como se ve este código:
Aquí está mi código de arrastrar y soltar:
var boxView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
view.backgroundColor = UIColor.blackColor()
addSavingPhotoView()
//Custom button to test this app
var button = UIButton(frame: CGRect(x: 20, y: 20, width: 20, height: 20))
button.backgroundColor = UIColor.redColor()
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(button)
}
func addSavingPhotoView() {
// You only need to adjust this frame to move it anywhere you want
boxView = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25, width: 180, height: 50))
boxView.backgroundColor = UIColor.whiteColor()
boxView.alpha = 0.8
boxView.layer.cornerRadius = 10
//Here the spinnier is initialized
var activityView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activityView.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityView.startAnimating()
var textLabel = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
textLabel.textColor = UIColor.grayColor()
textLabel.text = "Saving Photo"
boxView.addSubview(activityView)
boxView.addSubview(textLabel)
view.addSubview(boxView)
}
func buttonAction(sender:UIButton!) {
//When button is pressed it removes the boxView from screen
boxView.removeFromSuperview()
}
Aquí hay una versión de código abierto de esto: https://github.com/goktugyil/CozyLoadingActivity
Basado en mi respuesta anterior, aquí hay una solución más elegante con una clase personalizada:
Primero defina esta clase personalizada:
import UIKit
import Foundation
class ActivityIndicatorView
{
var view: UIView!
var activityIndicator: UIActivityIndicatorView!
var title: String!
init(title: String, center: CGPoint, width: CGFloat = 200.0, height: CGFloat = 50.0)
{
self.title = title
let x = center.x - width/2.0
let y = center.y - height/2.0
self.view = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
self.view.backgroundColor = UIColor(red: 255.0/255.0, green: 204.0/255.0, blue: 51.0/255.0, alpha: 0.5)
self.view.layer.cornerRadius = 10
self.activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
self.activityIndicator.color = UIColor.blackColor()
self.activityIndicator.hidesWhenStopped = false
let titleLabel = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
titleLabel.text = title
titleLabel.textColor = UIColor.blackColor()
self.view.addSubview(self.activityIndicator)
self.view.addSubview(titleLabel)
}
func getViewActivityIndicator() -> UIView
{
return self.view
}
func startAnimating()
{
self.activityIndicator.startAnimating()
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
}
func stopAnimating()
{
self.activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
self.view.removeFromSuperview()
}
//end
}
Ahora en tu UIViewController
clase:
var activityIndicatorView: ActivityIndicatorView!
override func viewDidLoad()
{
super.viewDidLoad()
self.activityIndicatorView = ActivityIndicatorView(title: "Processing...", center: self.view.center)
self.view.addSubview(self.activityIndicatorView.getViewActivityIndicator())
}
func doSomething()
{
self.activityIndicatorView.startAnimating()
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
//do something here that will taking time
self.activityIndicatorView.stopAnimating()
}
Para Swift 3
Uso
class LoginTVC: UITableViewController {
var loadingView : LoadingView!
override func viewDidLoad() {
super.viewDidLoad()
// CASE 1: To Show loadingView on load
loadingView = LoadingView(uiView: view, message: "Sending you verification code")
}
// CASE 2: To show loadingView on click of a button
@IBAction func showLoadingView(_ sender: UIButton) {
if let loaderView = loadingView{ // If loadingView already exists
if loaderView.isHidden() {
loaderView.show() // To show activity indicator
}
}
else{
loadingView = LoadingView(uiView: view, message: "Sending you verification code")
}
}
}
// CASE 3: To hide LoadingView on click of a button
@IBAction func hideLoadingView(_ sender: UIButton) {
if let loaderView = loadingView{ // If loadingView already exists
self.loadingView.hide()
}
}
}
LoadingView clase
class LoadingView {
let uiView : UIView
let message : String
let messageLabel = UILabel()
let loadingSV = UIStackView()
let loadingView = UIView()
let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
init(uiView: UIView, message: String) {
self.uiView = uiView
self.message = message
self.setup()
}
func setup(){
let viewWidth = uiView.bounds.width
let viewHeight = uiView.bounds.height
// Configuring the message label
messageLabel.text = message
messageLabel.textColor = UIColor.darkGray
messageLabel.textAlignment = .center
messageLabel.numberOfLines = 3
messageLabel.lineBreakMode = .byWordWrapping
// Creating stackView to center and align Label and Activity Indicator
loadingSV.axis = .vertical
loadingSV.distribution = .equalSpacing
loadingSV.alignment = .center
loadingSV.addArrangedSubview(activityIndicator)
loadingSV.addArrangedSubview(messageLabel)
// Creating loadingView, this acts as a background for label and activityIndicator
loadingView.frame = uiView.frame
loadingView.center = uiView.center
loadingView.backgroundColor = UIColor.darkGray.withAlphaComponent(0.3)
loadingView.clipsToBounds = true
// Disabling auto constraints
loadingSV.translatesAutoresizingMaskIntoConstraints = false
// Adding subviews
loadingView.addSubview(loadingSV)
uiView.addSubview(loadingView)
activityIndicator.startAnimating()
// Views dictionary
let views = [
"loadingSV": loadingSV
]
// Constraints for loadingSV
uiView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[loadingSV(300)]-|", options: [], metrics: nil, views: views))
uiView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-\(viewHeight / 3)-[loadingSV(50)]-|", options: [], metrics: nil, views: views))
}
// Call this method to hide loadingView
func show() {
loadingView.isHidden = false
}
// Call this method to show loadingView
func hide(){
loadingView.isHidden = true
}
// Call this method to check if loading view already exists
func isHidden() -> Bool{
if loadingView.isHidden == false{
return false
}
else{
return true
}
}
}
Puedes crear el tuyo propio. Por ejemplo:
Cree una vista con fondo blanco y esquinas redondeadas:
var view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
view.backgroundColor = UIColor.whiteColor()
view.layer.cornerRadius = 10
Agregue dos subvistas, ay UIActivityIndicatorView
a UILabel
:
var wait = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
wait.color = UIColor.blackColor()
wait.hidesWhenStopped = false
var text = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
text.text = "Processing..."
view.addSubview(wait)
view.addSubview(text)
IBAction
en mi controlador de vista y no pasó nada
view
Debe agregar como una subvista de la vista donde está tratando de mostrar la ruleta. Además, parece que la versión de Apple puede estar usando un UIVisualEffectView
para difuminar el fondo detrás de él.
wait.hidesWhenStopped = false
. Pregunta: ¿cómo ocultar el objeto view
?
Para el indicador de actividad, es mejor que cree una clase personalizada.
En lugar de crear UIActivityIndicator en cada UIViewController.Subclass UIView y usar desde cualquier UIViewController.
Actualizado para Swift 5.0:
import UIKit
import Foundation
class ProgressIndicator: UIView {
var indicatorColor:UIColor
var loadingViewColor:UIColor
var loadingMessage:String
var messageFrame = UIView()
var activityIndicator = UIActivityIndicatorView()
init(inview:UIView,loadingViewColor:UIColor,indicatorColor:UIColor,msg:String){
self.indicatorColor = indicatorColor
self.loadingViewColor = loadingViewColor
self.loadingMessage = msg
super.init(frame: CGRect(x: inview.frame.midX - 90, y: inview.frame.midY - 250 , width: 180, height: 50))
initalizeCustomIndicator()
}
convenience init(inview:UIView) {
self.init(inview: inview,loadingViewColor: UIColor.brown,indicatorColor:UIColor.black, msg: "Loading..")
}
convenience init(inview:UIView,messsage:String) {
self.init(inview: inview,loadingViewColor: UIColor.brown,indicatorColor:UIColor.black, msg: messsage)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func initalizeCustomIndicator(){
messageFrame.frame = self.bounds
activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
activityIndicator.tintColor = indicatorColor
activityIndicator.hidesWhenStopped = true
activityIndicator.frame = CGRect(x: self.bounds.origin.x + 6, y: 0, width: 20, height: 50)
print(activityIndicator.frame)
let strLabel = UILabel(frame:CGRect(x: self.bounds.origin.x + 30, y: 0, width: self.bounds.width - (self.bounds.origin.x + 30) , height: 50))
strLabel.text = loadingMessage
strLabel.adjustsFontSizeToFitWidth = true
strLabel.textColor = UIColor.white
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = loadingViewColor
messageFrame.alpha = 0.8
messageFrame.addSubview(activityIndicator)
messageFrame.addSubview(strLabel)
}
func start(){
//check if view is already there or not..if again started
if !self.subviews.contains(messageFrame){
activityIndicator.startAnimating()
self.addSubview(messageFrame)
}
}
func stop(){
if self.subviews.contains(messageFrame){
activityIndicator.stopAnimating()
messageFrame.removeFromSuperview()
}
}
}
Coloque esta clase en su proyecto y luego llame desde cualquier ViewController como
var indicator:ProgressIndicator?
override func viewDidLoad() {
super.viewDidLoad()
//indicator = ProgressIndicator(inview: self.view,messsage: "Hello from Nepal..")
//self.view.addSubview(indicator!)
//OR
indicator = ProgressIndicator(inview:self.view,loadingViewColor: UIColor.grayColor(), indicatorColor: UIColor.blackColor(), msg: "Landing within minutes,Please hold tight..")
self.view.addSubview(indicator!)
}
@IBAction func startBtn(sender: AnyObject) {
indicator!.start()
}
@IBAction func stopBtn(sender: AnyObject) {
indicator!.stop()
}
Según la respuesta de "MirekE", aquí hay un código que probé ahora y está funcionando:
var activityIndicator: UIActivityIndicatorView!
var viewActivityIndicator: UIView!
override func viewDidLoad()
{
super.viewDidLoad()
let width: CGFloat = 200.0
let height: CGFloat = 50.0
let x = self.view.frame.width/2.0 - width/2.0
let y = self.view.frame.height/2.0 - height/2.0
self.viewActivityIndicator = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
self.viewActivityIndicator.backgroundColor = UIColor(red: 255.0/255.0, green: 204.0/255.0, blue: 51.0/255.0, alpha: 0.5)
self.viewActivityIndicator.layer.cornerRadius = 10
self.activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
self.activityIndicator.color = UIColor.blackColor()
self.activityIndicator.hidesWhenStopped = false
let titleLabel = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
titleLabel.text = "Processing..."
self.viewActivityIndicator.addSubview(self.activityIndicator)
self.viewActivityIndicator.addSubview(titleLabel)
self.view.addSubview(self.viewActivityIndicator)
}
func doSometing()
{
self.activityIndicator.startAnimating()
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
//do something here that will taking time
self.activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
self.viewActivityIndicator.removeFromSuperview()
}
clase de controlador de actividad simple !!!
class ActivityIndicator: UIVisualEffectView {
let activityIndictor: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
let label: UILabel = UILabel()
let blurEffect = UIBlurEffect(style: .Dark)
let vibrancyView: UIVisualEffectView
init() {
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(effect: blurEffect)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(coder: aDecoder)
self.setup()
}
func setup() {
contentView.addSubview(vibrancyView)
vibrancyView.contentView.addSubview(activityIndictor)
activityIndictor.startAnimating()
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superview = self.superview {
let width: CGFloat = 75.0
let height: CGFloat = 75.0
self.frame = CGRectMake(superview.frame.size.width / 2 - width / 2,
superview.frame.height / 2 - height / 2,
width,
height)
vibrancyView.frame = self.bounds
let activityIndicatorSize: CGFloat = 40
activityIndictor.frame = CGRectMake(18, height / 2 - activityIndicatorSize / 2,
activityIndicatorSize,
activityIndicatorSize)
layer.cornerRadius = 8.0
layer.masksToBounds = true
}
}
func show() {
self.hidden = false
}
func hide() {
self.hidden = true
}}
uso: -
let activityIndicator = ActivityIndicator()
self.view.addSubview(activityIndicator)
esconder :-
activityIndicator.hide()
Xcode 10.1 • Swift 4.2
import UIKit
class ProgressHUD: UIVisualEffectView {
var title: String?
var theme: UIBlurEffect.Style = .light
let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 160, height: 46))
let activityIndicator = UIActivityIndicatorView()
init(title: String, theme: UIBlurEffect.Style = .light) {
super.init(effect: UIBlurEffect(style: theme))
self.title = title
self.theme = theme
[activityIndicator, strLabel].forEach(contentView.addSubview(_:))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superview = self.superview {
frame = CGRect(x: superview.frame.midX - strLabel.frame.width / 2,
y: superview.frame.midY - strLabel.frame.height / 2, width: 160, height: 46)
layer.cornerRadius = 15.0
layer.masksToBounds = true
activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
activityIndicator.startAnimating()
strLabel.text = title
strLabel.font = .systemFont(ofSize: 14, weight: UIFont.Weight.medium)
switch theme {
case .dark:
strLabel.textColor = .white
activityIndicator.style = .white
default:
strLabel.textColor = .gray
activityIndicator.style = .gray
}
}
}
func show() {
self.isHidden = false
}
func hide() {
self.isHidden = true
}
}
Utilizar:
let progress = ProgressHUD(title: "Authorization", theme: .dark)
[progress].forEach(view.addSubview(_:))
Úselo como a continuación:
var progressView: ProgressView?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.progressView = ProgressView(message: "Work in progress!",
theme: .dark,
isModal: true)
}
@IBAction func onPause(_ sender: AnyObject) {
self.progressView.show()
}
@IBAction func onResume(_ sender: AnyObject) {
self.progressView.hide()
}
import UIKit
class ProgressView: UIView {
enum Theme {
case light
case dark
}
var theme: Theme
var container: UIStackView
var activityIndicator: UIActivityIndicatorView
var label: UILabel
var glass: UIView
private var message: String
private var isModal: Bool
init(message: String, theme: theme, isModal: Bool) {
// Init
self.message = message
self.theme = theme
self.isModal = isModal
self.container = UIStackView()
self.activityIndicator = UIActivityIndicatorView()
self.label = UILabel()
self.glass = UIView()
// Get proper width by text message
let fontName = self.label.font.fontName
let fontSize = self.label.font.pointSize
if let font = UIFont(name: fontName, size: fontSize) {
let fontAttributes = [NSFontAttributeName: font]
let size = (message as NSString).size(attributes: fontAttributes)
super.init(frame: CGRect(x: 0, y: 0, width: size.width + 50, height: 50))
} else {
super.init(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
}
// Detect rotation
NotificationCenter.default.addObserver(self, selector: #selector(onRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
// Style
self.layer.cornerRadius = 3
if (self.theme == .dark) {
self.backgroundColor = .darkGray
} else {
self.backgroundColor = .lightGray
}
// Label
if self.theme == .dark {
self.label.textColor = .white
}else{
self.label.textColor = .black
}
self.label.text = self.message
// Container
self.container.frame = self.frame
self.container.spacing = 5
self.container.layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
self.container.isLayoutMarginsRelativeArrangement = true
// Activity indicator
if (self.theme == .dark) {
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
self.activityIndicator.color = .white
} else {
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle:.whiteLarge)
self.activityIndicator.color = .black
}
self.activityIndicator.startAnimating()
// Add them to container
// First glass
if let superview = UIApplication.shared.keyWindow {
if (self.isModal) {
// glass
self.glass.frame = superview.frame;
if (self.theme == .dark) {
self.glass.backgroundColor = UIColor.black.withAlphaComponent(0.5)
} else {
self.glass.backgroundColor = UIColor.white.withAlphaComponent(0.5)
}
superview.addSubview(glass)
}
}
// Then activity indicator and label
container.addArrangedSubview(self.activityIndicator)
container.addArrangedSubview(self.label)
// Last attach it to container (StackView)
self.addSubview(container)
if let superview = UIApplication.shared.keyWindow {
self.center = superview.center
superview.addSubview(self)
}
//Do not show until show() is called
self.hide()
}
required init(coder: NSCoder) {
self.theme = .dark
self.Message = "Not set!"
self.isModal = true
self.container = UIStackView()
self.activityIndicator = UIActivityIndicatorView()
self.label = UILabel()
self.glass = UIView()
super.init(coder: coder)!
}
func onRotate() {
if let superview = self.superview {
self.glass.frame = superview.frame
self.center = superview.center
// superview.addSubview(self)
}
}
public func show() {
self.glass.isHidden = false
self.isHidden = false
}
public func hide() {
self.glass.isHidden = true
self.isHidden = true
}
}
Este código funciona en SWIFT 2.0.
Debe declarar una variable para inicializar UIActivityIndicatorView
let actInd: UIActivityIndicatorView = UIActivityIndicatorView()
Después de inicializar, ponga este código en su controlador.
actInd.center = ImageView.center
actInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
view.addSubview(actInd)
actInd.startAnimating()
después de que se complete el proceso de descarga, oculte una animación.
self.actInd.stopAnimating()
En Swift 3
Declarar variables que usaremos
var activityIndicator = UIActivityIndicatorView()
let loadingView = UIView()
let loadingLabel = UILabel()
Establecer etiqueta, vista e indicador de actividad
func setLoadingScreen(myMsg : String) {
let width: CGFloat = 120
let height: CGFloat = 30
let x = (self.view.frame.width / 2) - (width / 2)
let y = (169 / 2) - (height / 2) + 60
loadingView.frame = CGRect(x: x, y: y, width: width, height: height)
self.loadingLabel.textColor = UIColor.white
self.loadingLabel.textAlignment = NSTextAlignment.center
self.loadingLabel.text = myMsg
self.loadingLabel.frame = CGRect(x: 0, y: 0, width: 160, height: 30)
self.loadingLabel.isHidden = false
self.activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.white
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
self.activityIndicator.startAnimating()
loadingView.addSubview(self.spinner)
loadingView.addSubview(self.loadingLabel)
self.view.addSubview(loadingView)
}
Iniciar animación
@IBAction func start_animation(_ sender: Any) {
setLoadingScreen(myMsg: "Loading...")
}
Detener animación
@IBAction func stop_animation(_ sender: Any) {
self.spinner.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
self.loadingLabel.isHidden = true
}
import UIKit
class ViewControllerUtils {
let containerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor(white: 0, alpha: 0.3)
return view
}()
let loadingView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor(white: 0, alpha: 0.7)
view.clipsToBounds = true
view.layer.cornerRadius = 10
return view
}()
let activityIndicatorView: UIActivityIndicatorView = {
let aiv = UIActivityIndicatorView()
aiv.translatesAutoresizingMaskIntoConstraints = false
aiv.style = UIActivityIndicatorView.Style.whiteLarge
return aiv
}()
let loadingLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Loading..."
label.textAlignment = .center
label.textColor = .white
label.font = .systemFont(ofSize: 15, weight: UIFont.Weight.medium)
return label
}()
func showLoader() {
guard let window = UIApplication.shared.keyWindow else { return }
window.addSubview(containerView)
containerView.addSubview(loadingView)
loadingView.addSubview(activityIndicatorView)
loadingView.addSubview(loadingLabel)
containerView.leftAnchor.constraint(equalTo: window.leftAnchor).isActive = true
containerView.rightAnchor.constraint(equalTo: window.rightAnchor).isActive = true
containerView.topAnchor.constraint(equalTo: window.topAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: window.bottomAnchor).isActive = true
loadingView.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
loadingView.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
loadingView.widthAnchor.constraint(equalToConstant: 120).isActive = true
loadingView.heightAnchor.constraint(equalToConstant: 120).isActive = true
activityIndicatorView.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
activityIndicatorView.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
activityIndicatorView.widthAnchor.constraint(equalToConstant: 60).isActive = true
activityIndicatorView.heightAnchor.constraint(equalToConstant: 60).isActive = true
loadingLabel.leftAnchor.constraint(equalTo: loadingView.leftAnchor).isActive = true
loadingLabel.rightAnchor.constraint(equalTo: loadingView.rightAnchor).isActive = true
loadingLabel.bottomAnchor.constraint(equalTo: loadingView.bottomAnchor).isActive = true
loadingLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
DispatchQueue.main.async {
self.activityIndicatorView.startAnimating()
}
}
func hideLoader() {
DispatchQueue.main.async {
self.activityIndicatorView.stopAnimating()
self.activityIndicatorView.removeFromSuperview()
self.loadingLabel.removeFromSuperview()
self.loadingView.removeFromSuperview()
self.containerView.removeFromSuperview()
}
}
}
//// In order to show the activity indicator, call the function from your view controller
// let viewControllerUtils = ViewControllerUtils()
// viewControllerUtils.showLoader()
//// In order to hide the activity indicator, call the function from your view controller
// viewControllerUtils.hideLoader()
class ViewControllerUtils2 {
var container: UIView = UIView()
var loadingView: UIView = UIView()
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
let loadingLabel = UILabel()
func showLoader(_ uiView: UIView) {
container.frame = uiView.frame
container.center = uiView.center
container.backgroundColor = UIColor(white: 0, alpha: 0.3)
loadingView.frame = CGRect(x: 0, y: 0, width: 120, height: 120)
loadingView.center = uiView.center
loadingView.backgroundColor = UIColor(white: 0, alpha: 0.7)
loadingView.clipsToBounds = true
loadingView.layer.cornerRadius = 10
activityIndicator.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
activityIndicator.style = UIActivityIndicatorView.Style.whiteLarge
activityIndicator.center = CGPoint(x: loadingView.frame.size.width / 2, y: loadingView.frame.size.height / 2)
loadingLabel.frame = CGRect(x: 0, y: 80, width: 120, height: 40)
loadingLabel.text = "Loading..."
loadingLabel.textAlignment = .center
loadingLabel.textColor = .white
loadingLabel.font = .systemFont(ofSize: 15, weight: UIFont.Weight.medium)
uiView.addSubview(container)
container.addSubview(loadingView)
loadingView.addSubview(activityIndicator)
loadingView.addSubview(loadingLabel)
DispatchQueue.main.async {
self.activityIndicator.startAnimating()
}
}
func hideLoader() {
DispatchQueue.main.async {
self.activityIndicator.stopAnimating()
self.activityIndicator.removeFromSuperview()
self.loadingLabel.removeFromSuperview()
self.loadingView.removeFromSuperview()
self.container.removeFromSuperview()
}
}
}