如何在UIAlertController的中心显示活动指标?

我目前有一个UIAlertController屏幕上显示。 警报的视图应该只在警报的中心显示2个元素,一个标题和一个UIActivityIndicatorView 。 以下是显示警报及其元素的function。

 func displaySignUpPendingAlert() -> UIAlertController { //Create the UIAlertController let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .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 } 

但是,活动指示符不显示在视图的中央,实际上它显示在屏幕的右下方,远离视图。 这是什么原因?

编辑:我明白,我可以硬编码指标的位置的数字,但我希望警报工作在多个设备的多个屏幕大小和方向。

确保在创build视图时设置框架属性。

 func displaySignUpPendingAlert() -> UIAlertController { //create an alert controller let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .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 // required 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 } 

到@ 62鲨:

 let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .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) 

如果有人感兴趣,我把答案转换成Objective C,

 UIAlertController *pending = [UIAlertController alertControllerWithTitle:nil message:@"Please wait...\n\n" preferredStyle: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]; 

干杯

对于喜欢UIActivityIndicatorView左边alignment的UIActivityIndicatorViewUIAlertController.title ,这是我在Swift中为所有设备工作的解决scheme:

 let alert = UIAlertController(title: NSLocalizedString("Authenticating...", comment: "Authenticating"), message: nil, preferredStyle: .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); 

但是,要在视图中心alignmentUIActivityIndicatorView ,您可以更改如下:

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

苹果不鼓励直接inheritanceUIAlertController,所以我做了一个类,显示UIAlertController居中的UIActivityIndi​​cator和处理取消条件与类协议。

 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, preferredStyle: 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) }) } } 

我build议使用lazy var来初始化类。

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

这是一个示例代码的链接: https : //github.com/cgilleeny/BusyAlertExample.git

那么试试这个代码。

 UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"Creating new user\n\n\n" preferredStyle: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

框架矩形,在其超级视图的坐标系中描述视图的位置和大小。 你的pending.view.frame == CGRect(0,0,0,0)

需要在完成块设置指标中心,当你的警报将有超视图

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

尝试这个:

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

您还需要检查横向模式和反向宽度和高度。

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

也许你可以得到警报视图的位置?

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

并使用它来dynamic放置您的活动视图,即与variables?

当然,你也可能想把大小除以2并加上,使其居中。

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

在迅速:

 activityIndicator.center = self.view.center 

如果你有一个工具栏或一个navController你可能要改变点,但否则,中心是中心…

如果你仍然有问题,也许这个教程会有所帮助。 如果你想把它放在一个表格视图控制器中, 这个答案可能会有所帮助。

我有同样的问题,使用框架定位不适合我。 林益民的回答对我来说非常接近,但我只想提出一个非可视化格式的约束:

 //... 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)) //... 

我必须实现NSLayoutConstraint s把UIActivityIndicatorView放在UIAlertController的中心

对于Swift 3:

 let loadingAlertController = UIAlertController(title: "Loading", message: nil, preferredStyle: .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) 

转换@ petesalt的答案Swift 3:

 let pending = UIAlertController(title: "Saving, please wait...", message: nil, preferredStyle: .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)