¿Cómo mostrar el indicador de actividad en el centro de UIAlertController?

Actualmente, tengo un UIAlertController en la pantalla. La vista de la alerta solo debe mostrar 2 elementos, un título y una UIActivityIndicatorView en el centro de la alerta. A continuación se muestra la function que muestra la alerta y sus elementos.

 func displaySignUpPendingAlert() -> UIAlertController { //Create the UIAlertController let pending = UIAlertController(title: "Creating New User", message: nil, prefernetworkingStyle: .Alert) //Create the activity indicator to display in it. let indicator = UIActivityIndicatorView(frame: CGRectMake(pending.view.frame.width / 2.0, pending.view.frame.height / 2.0, 20.0, 20.0)) indicator.center = CGPointMake(pending.view.frame.width / 2.0, pending.view.frame.height / 2.0) //Add the activity indicator to the alert's view pending.view.addSubview(indicator) //Start animating indicator.startAnimating() self.presentViewController(pending, animated: true, completion: nil) return pending } 

Sin embargo, el indicador de actividad no se muestra en el centro de la vista, de hecho, se muestra en la parte inferior derecha de la pantalla, muy alejado de la vista. ¿Cuál es la razón para esto?

EDIT: Comprendo que puedo usar numbers de código fijo para la position del indicador, pero quiero que la alerta funcione en múltiples dispositivos con múltiples tamaños de pantalla y orientaciones.

Asegúrese de establecer la propiedad de marco cuando esté creando una vista.

 func displaySignUpPendingAlert() -> UIAlertController { //create an alert controller let pending = UIAlertController(title: "Creating New User", message: nil, prefernetworkingStyle: .Alert) //create an activity indicator let indicator = UIActivityIndicatorView(frame: pending.view.bounds) indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight] //add the activity indicator as a subview of the alert controller's view pending.view.addSubview(indicator) indicator.isUserInteractionEnabled = false // requinetworking otherwise if there buttons in the UIAlertController you will not be able to press them indicator.startAnimating() self.presentViewController(pending, animated: true, completion: nil) return pending } 

Para @ 62Shark:

 let pending = UIAlertController(title: "Creating New User", message: nil, prefernetworkingStyle: .Alert) let indicator = UIActivityIndicatorView() indicator.setTranslatesAutoresizingMaskIntoConstraints(false) pending.view.addSubview(indicator) let views = ["pending" : pending.view, "indicator" : indicator] var constraints = NSLayoutConstraint.constraintsWithVisualFormat("V:[indicator]-(-50)-|", options: nil, metrics: nil, views: views) constraints += NSLayoutConstraint.constraintsWithVisualFormat("H:|[indicator]|", options: nil, metrics: nil, views: views) pending.view.addConstraints(constraints) indicator.userInteractionEnabled = false indicator.startAnimating() self.presentViewController(pending, animated: true, completion: nil) 

Convertí la respuesta al Objetivo C, si alguien está interesado:

 UIAlertController *pending = [UIAlertController alertControllerWithTitle:nil message:@"Please wait...\n\n" prefernetworkingStyle:UIAlertControllerStyleAlert]; UIActivityIndicatorView* indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; indicator.color = [UIColor blackColor]; indicator.translatesAutoresizingMaskIntoConstraints=NO; [pending.view addSubview:indicator]; NSDictionary * views = @{@"pending" : pending.view, @"indicator" : indicator}; NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(20)-|" options:0 metrics:nil views:views]; NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views]; NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal]; [pending.view addConstraints:constraints]; [indicator setUserInteractionEnabled:NO]; [indicator startAnimating]; [self presentViewController:pending animated:YES completion:nil]; 

Aclamaciones

Apple no fomenta la subclass directamente UIAlertController, así que hice una class que muestra UIAlertController con UIActivityIndicator centrado y maneja la condición de cancelación con un protocolo de class.

 import Foundation import UIKit protocol BusyAlertDelegate { func didCancelBusyAlert() } class BusyAlert { var busyAlertController: UIAlertController? var presentingViewController: UIViewController? var activityIndicator: UIActivityIndicatorView? var delegate:BusyAlertDelegate? init (title:String, message:String, presentingViewController: UIViewController) { busyAlertController = UIAlertController(title: title, message: message, prefernetworkingStyle: UIAlertControllerStyle.Alert) busyAlertController!.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel Button"), style: UIAlertActionStyle.Cancel, handler:{(alert: UIAlertAction!) in delegate?.didCancelBusyAlert() })) self.presentingViewController = presentingViewController activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray) busyAlertController!.view.addSubview(activityIndicator!) } func display() { dispatch_async(dispatch_get_main_queue(), { self.presentingViewController!.presentViewController(self.busyAlertController!, animated: true, completion: { self.activityIndicator!.translatesAutoresizingMaskIntoConstraints = false self.busyAlertController!.view.addConstraint(NSLayoutConstraint(item: self.activityIndicator!, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.busyAlertController!.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)) self.busyAlertController!.view.addConstraint(NSLayoutConstraint(item: self.activityIndicator!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.busyAlertController!.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)) self.activityIndicator!.startAnimating() }) }) } func dismiss() { dispatch_async(dispatch_get_main_queue(), { self.busyAlertController?.dismissViewControllerAnimated(true, completion: nil) }) } } 

Recomiendo usar var perezoso para inicializar la class.

 lazy var busyAlertController: BusyAlert = { let busyAlert = BusyAlert(title: "Lengthy Task", message: "Please wait...", presentingViewController: self) busyAlert.delegate = self return busyAlert }() 

Aquí hay un enlace al código de muestra: https://github.com/cgilleeny/BusyAlertExample.git

Bueno, testing este código.

 UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"Creating new user\n\n\n" prefernetworkingStyle:UIAlertControllerStyleAlert]; UIActivityIndicatorView *loader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; loader.center = CGPointMake(130.5, 65.5); loader.color = [UIColor blackColor]; [loader startAnimating]; [alert.view loader]; [self presentViewController:alert animated:NO completion:nil]; 

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/frame

El rectángulo del marco, que describe la location y el tamaño de la vista en el sistema de coorderadas de su supervisor. que su pending.view.frame == CGRect (0,0,0,0)

Necesita establecer el centro del indicador en el bloque de finalización allí, cuando su alerta tendrá supervisión

 self.presentViewController(pending, animated: true, completion: nil) 

Para aquellos que prefieren UIActivityIndicatorView alineados a la izquierda del UIAlertController.title , esta es mi solución en Swift para todos los dispositivos:

 let alert = UIAlertController(title: NSLocalizedString("Authenticating...", comment: "Authenticating"), message: nil, prefernetworkingStyle: .Alert); let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray) activityIndicator.frame = activityIndicator.frame.rectByOffsetting(dx: 8, dy: (alert.view.bounds.height - activityIndicator.frame.height)/2); activityIndicator.autoresizingMask = .FlexibleRightMargin | .FlexibleTopMargin | .FlexibleBottomMargin activityIndicator.color = themeManager().currentTheme.navigationBarTintColor; activityIndicator.startAnimating(); alert.view.addSubview(activityIndicator); self.presentViewController(progressAlert, animated: true, completion: nil); 

Sin embargo, para alinear el UIActivityIndicatorView en el centro de vistas, puede cambiar de la siguiente manera:

 activityIndicator.center = CGPoint(x: (alert.view.bounds.width)/2, y: (alert.view.bounds.height)/2) activityIndicator.autoresizingMask = .FlexibleLeftMargin | .FlexibleRightMargin | .FlexibleTopMargin | .FlexibleBottomMargin 

Prueba esto:

 activityView.center = CGPointMake(self.view.bounds.size.width/2.0, self.view.bounds.size.height / 2.0) 

También deberá verificar el modo horizontal y el ancho y la altura inversa.

 if(landscapeMode)activityView.center = CGPointMake(self.view.bounds.size.height/2.0, self.view.bounds.size.width / 2.0) 

Tal vez pueda get la position de vista de alerta?

 alert.view.frame.origin.x alert.view.frame.origin.y 

y usarlo para ubicar su vista de actividad dinámicamente, es decir, con las variables?

Por supuesto, también es posible que desee dividir el tamaño por 2 y agregarlo para que esté centrado también.

 alert.view.frame.size.height alert.view.frame.size.width 

En swift:

 activityIndicator.center = self.view.center 

Si tiene una barra de herramientas o un NavController, es posible que desee cambiar el punto pero, de lo contrario, el centro está en el centro …

Si aún tienes problemas, quizás este tutorial te ayude. Si está intentando centrarlo en un controller de vista de tabla, esta respuesta podría ayudar.

Tuve el mismo problema y usar el posicionamiento del marco no funcionó para mí. La respuesta de Yimin Lin fue muy cercana para mí, pero solo quería presentar una alternativa usando restricciones en formatting no visual:

 //... indicator.setTranslatesAutoresizingMaskIntoConstraints(false) alert.view.addSubview(indicator) alert.view.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: alert.view, attribute: attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)) alert.view.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: alert.view, attribute: attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)) //... 

Tengo que implementar NSLayoutConstraint s para poner el UIActivityIndicatorView en el centro del UIAlertController

Para Swift 3:

 let loadingAlertController = UIAlertController(title: "Loading", message: nil, prefernetworkingStyle: .alert) let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray) activityIndicator.translatesAutoresizingMaskIntoConstraints = false loadingAlertController.view.addSubview(activityIndicator) let xConstraint = NSLayoutConstraint(item: activityIndicator, attribute: .centerX, relatedBy: .equal, toItem: loadingAlertController.view, attribute: .centerX, multiplier: 1, constant: 0) let yConstraint = NSLayoutConstraint(item: activityIndicator, attribute: .centerY, relatedBy: .equal, toItem: loadingAlertController.view, attribute: .centerY, multiplier: 1.4, constant: 0) NSLayoutConstraint.activate([ xConstraint, yConstraint]) activityIndicator.isUserInteractionEnabled = false activityIndicator.startAnimating() let height: NSLayoutConstraint = NSLayoutConstraint(item: loadingAlertController.view, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 80) loadingAlertController.view.addConstraint(height); self.present(loadingAlertController, animated: true, completion: nil) 

La respuesta de @petesalt a Swift 3:

 let pending = UIAlertController(title: "Saving, please wait...", message: nil, prefernetworkingStyle: .alert) let indicator = UIActivityIndicatorView() indicator.translatesAutoresizingMaskIntoConstraints = false pending.view.addSubview(indicator) let views = ["pending" : pending.view, "indicator" : indicator] var constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[indicator]-(-50)-|", options: NSLayoutFormatOptions.alignAllCenterY, metrics: nil, views: views) constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[indicator]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: views) pending.view.addConstraints(constraints) indicator.isUserInteractionEnabled = false indicator.startAnimating() self.present(pending, animated: true, completion: nil)