ios swift uiview overlay

Cargar una "superposición" al ejecutar tareas largas en iOS



swift uiview (9)

¿Cuál es el ejemplo para cargar superposición en la aplicación Swift IOS cuando se realizan tareas largas? Ejemplo para cargar datos desde un servidor remoto. Busqué en Google pero no encontré ninguna respuesta.

Actualizado:

Gracias por @Sebastian Dressler, esta es una manera simple. Actualicé mi código y funciona bien

public class LoadingOverlay{ var overlayView = UIView() var activityIndicator = UIActivityIndicatorView() class var shared: LoadingOverlay { struct Static { static let instance: LoadingOverlay = LoadingOverlay() } return Static.instance } public func showOverlay(view: UIView) { overlayView.frame = CGRectMake(0, 0, 80, 80) overlayView.center = view.center overlayView.backgroundColor = UIColor(hex: 0x444444, alpha: 0.7) overlayView.clipsToBounds = true overlayView.layer.cornerRadius = 10 activityIndicator.frame = CGRectMake(0, 0, 40, 40) activityIndicator.activityIndicatorViewStyle = .WhiteLarge activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2) overlayView.addSubview(activityIndicator) view.addSubview(overlayView) activityIndicator.startAnimating() } public func hideOverlayView() { activityIndicator.stopAnimating() overlayView.removeFromSuperview() } }

dejar de usar:

LoadingOverlay.shared.showOverlay(self.view) //To to long tasks LoadingOverlay.shared.hideOverlayView()



Las respuestas anteriores agregan una vista de carga, pero no bloquea los eventos de clic en la pantalla y tampoco proporciona superposición para el resto de la pantalla. Puede lograrlo de la siguiente manera:

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .Alert) alert.view.tintColor = UIColor.blackColor() let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50)) as UIActivityIndicatorView loadingIndicator.hidesWhenStopped = true loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray loadingIndicator.startAnimating(); alert.view.addSubview(loadingIndicator) presentViewController(alert, animated: true, completion: nil)

Swift 3.0

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert) let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) loadingIndicator.hidesWhenStopped = true loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray loadingIndicator.startAnimating(); alert.view.addSubview(loadingIndicator) present(alert, animated: true, completion: nil)

Swift 4.0 y más reciente

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert) let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) loadingIndicator.hidesWhenStopped = true loadingIndicator.style = UIActivityIndicatorView.Style.gray loadingIndicator.startAnimating(); alert.view.addSubview(loadingIndicator) present(alert, animated: true, completion: nil)

y puedes ocultarlo de la siguiente manera:

dismiss(animated: false, completion: nil)

Se mostrará de la siguiente manera:


Para agregar a las respuestas dadas, es posible que encuentre problemas si intenta ejecutar el código a veces. Personalmente, hubo una ocasión en la que no se llamó correctamente a showOverlay (porque estaba tratando de pasar a una escena, luego llamé inmediatamente a esta función durante viewDidLoad).

Si se encuentra con un problema similar al mío, hay una solución para el código y un cambio de enfoque que recomiendo.

REVISIÓN: coloque ambos bloques de código como cierres de una llamada dispatch_async, así:

dispatch_async(dispatch_get_main_queue(), { //code });

ENFOQUE: cuando llame a su código, realice una llamada dispatch_after a la cola principal para retrasar la llamada unos pocos milisegundos.

¿El razonamiento? Simplemente le está pidiendo a la interfaz de usuario que haga demasiado durante viewDidLoad.

Si este apéndice de la solución ayudara, me alegraría.

-Joel Long

PS Solution funcionó para XCode v6.3.2


Para cualquiera que llegue tarde como yo, hice algunas modificaciones al código @Sonrobby. Según tengo entendido, @Sonrobby agrega la actividad a la superposición en cada llamada showOverlay . Y parte de la configuración se puede pasar a la función init, dejando solo la ubicación en el método showOverlay .

También cambio el fondo de la superposición a negro, ya que mi aplicación es principalmente blanca.

Aquí está el código:

public class LoadingOverlay{ var overlayView : UIView! var activityIndicator : UIActivityIndicatorView! class var shared: LoadingOverlay { struct Static { static let instance: LoadingOverlay = LoadingOverlay() } return Static.instance } init(){ self.overlayView = UIView() self.activityIndicator = UIActivityIndicatorView() overlayView.frame = CGRectMake(0, 0, 80, 80) overlayView.backgroundColor = UIColor(white: 0, alpha: 0.7) overlayView.clipsToBounds = true overlayView.layer.cornerRadius = 10 overlayView.layer.zPosition = 1 activityIndicator.frame = CGRectMake(0, 0, 40, 40) activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2) activityIndicator.activityIndicatorViewStyle = .WhiteLarge overlayView.addSubview(activityIndicator) } public func showOverlay(view: UIView) { overlayView.center = view.center view.addSubview(overlayView) activityIndicator.startAnimating() } public func hideOverlayView() { activityIndicator.stopAnimating() overlayView.removeFromSuperview() } }


Respuesta actualizada de @sonrobby, se agregó una vista de fondo y manejo de orientación a través de la máscara de cambio de tamaño ... esto se puede usar para cosas simples

public class LoadingOverlay{ var overlayView = UIView() var activityIndicator = UIActivityIndicatorView() var bgView = UIView() class var shared: LoadingOverlay { struct Static { static let instance: LoadingOverlay = LoadingOverlay() } return Static.instance } public func showOverlay(view: UIView) { bgView.frame = view.frame bgView.backgroundColor = UIColor.gray bgView.addSubview(overlayView) bgView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin,.flexibleHeight, .flexibleWidth] overlayView.frame = CGRect(x: 0, y: 0, width: 80, height: 80) overlayView.center = view.center overlayView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin] overlayView.backgroundColor = UIColor.black overlayView.clipsToBounds = true overlayView.layer.cornerRadius = 10 activityIndicator.frame = CGRect(x: 0, y: 0, width: 40, height: 40) activityIndicator.activityIndicatorViewStyle = .whiteLarge activityIndicator.center = CGPoint(x: overlayView.bounds.width / 2, y: overlayView.bounds.height / 2) overlayView.addSubview(activityIndicator) view.addSubview(bgView) self.activityIndicator.startAnimating() } public func hideOverlayView() { activityIndicator.stopAnimating() bgView.removeFromSuperview() } }

si lo agrega a la ventana clave, puede pasar por encima de su barra de navegación y pestañas también ... algo como esto

LoadingOverlay.shared.showOverlay(view: UIApplication.shared.keyWindow!)


Simplemente cree una vista de superposición, que agregue a su vista principal y elimínela una vez que haya completado su tarea, por ejemplo, para agregarla:

var overlay : UIView? // This should be a class variable [ ... ] overlay = UIView(frame: view.frame) overlay!.backgroundColor = UIColor.blackColor() overlay!.alpha = 0.8 view.addSubview(overlay!)

Para remoción:

overlay?.removeFromSuperview()


Swift 3.

Utilicé el código de @ Lucho en su respuesta a continuación y cambié el color de fondo de la superposición para borrarlo y agregué un color giratorio.

public class LoadingOverlay { var overlayView : UIView! var activityIndicator : UIActivityIndicatorView! class var shared: LoadingOverlay { struct Static { static let instance: LoadingOverlay = LoadingOverlay() } return Static.instance } init(){ self.overlayView = UIView() self.activityIndicator = UIActivityIndicatorView() overlayView.frame = CGRect(0, 0, 80, 80) overlayView.backgroundColor = .clear overlayView.clipsToBounds = true overlayView.layer.cornerRadius = 10 overlayView.layer.zPosition = 1 activityIndicator.frame = CGRect(0, 0, 40, 40) activityIndicator.center = CGPoint(overlayView.bounds.width / 2, overlayView.bounds.height / 2) activityIndicator.activityIndicatorViewStyle = .whiteLarge activityIndicator.color = .gray overlayView.addSubview(activityIndicator) } public func showOverlay(view: UIView) { overlayView.center = view.center view.addSubview(overlayView) activityIndicator.startAnimating() } public func hideOverlayView() { activityIndicator.stopAnimating() overlayView.removeFromSuperview() } }



Fondo borroso + indicador de actividad, ejemplo de Swift 5

extension UIView { func showBlurLoader() { let blurLoader = BlurLoader(frame: frame) self.addSubview(blurLoader) } func removeBluerLoader() { if let blurLoader = subviews.first(where: { $0 is BlurLoader }) { blurLoader.removeFromSuperview() } } } class BlurLoader: UIView { var blurEffectView: UIVisualEffectView? override init(frame: CGRect) { let blurEffect = UIBlurEffect(style: .dark) let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.frame = frame blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.blurEffectView = blurEffectView super.init(frame: frame) addSubview(blurEffectView) addLoader() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func addLoader() { guard let blurEffectView = blurEffectView else { return } let activityIndicator = UIActivityIndicatorView(style: .whiteLarge) activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50) blurEffectView.contentView.addSubview(activityIndicator) activityIndicator.center = blurEffectView.contentView.center activityIndicator.startAnimating() } }