如何将 UIActivityIndi​​catorView 放在 UIAlertController 中?

Posted

技术标签:

【中文标题】如何将 UIActivityIndi​​catorView 放在 UIAlertController 中?【英文标题】:How do I put a UIActivityIndicatorView in a UIAlertController? 【发布时间】:2015-07-14 13:38:37 【问题描述】:

我们将不再使用 MBProgressHUD,因为它在我们的应用中过于故障,并且没有阻止用户输入或提供取消按钮等功能。

所以,我尝试实现Swipesight's How to display activity indicator in center of UIAlertController?,但遇到了指标定位不当:

它是绿色的,因为我们的应用程序的色调是绿色的。

如您所见,它不在控制器的白色矩形部分,而是在灰色背景中。这使用了类似于他的“@62Shark”解决方案:

// in implementation:

@property (nonatomic, strong) UIActivityIndicatorView *spinner;
@property (nonatomic, strong) UIAlertController *alertController;


// in init:

_alertController = [UIAlertController alertControllerWithTitle: @"Loading"
                                                         message: nil
                                                  preferredStyle: UIAlertControllerStyleAlert];
_spinner = [UIActivityIndicatorView new];
_spinner.translatesAutoresizingMaskIntoConstraints = false;
_spinner.userInteractionEnabled = false;
_spinner.color = [ThemingAssistant tintColor];
_spinner.frame = _alertController.view.bounds;
_spinner.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[_spinner startAnimating];
[_alertController.view addSubview: _spinner];


// ...

- (void) showOn: (UIViewController *)target
          title: (NSString *)title
        message: (NSString *)message
      canCancel: (BOOL)canCancel

    self.alertController.title = title;
    self.alertController.message = message;

    if (canCancel)
    
        [self.alertController addAction:[UIAlertAction actionWithTitle: @"Cancel"
                                                                 style: UIAlertActionStyleCancel
                                                               handler: ^(UIAlertAction *name)
                                                                   [self customDismiss];
                                                               ]];
    

    NSDictionary *views = @@"pending"   : self.alertController.view,
                            @"indicator" : self.spinner;
    NSArray *constraints =
    [NSLayoutConstraint constraintsWithVisualFormat: @"V:[indicator]-(-50)-|"
                                            options: 0
                                            metrics: nil
                                              views: views];
    [constraints arrayByAddingObjectsFromArray:
     [NSLayoutConstraint constraintsWithVisualFormat: @"H:|[indicator]|"
                                             options: 0
                                             metrics: nil
                                               views: views]];


    [target presentViewController: self.alertController
                         animated: true
                       completion: nil];

即使它在白色矩形中,我也担心它可能会进入文本(另外,当我将它放入其中时,我希望它位于中间顶部,就像 MBProgressHUD 一样),所以我会需要一种方法为其保留一些空间。

所以,我的问题有两个:如何在UIAlertController 的白色矩形中为UIActivityIndicatorView 保留空间,然后如何实际放置它在那里?

【问题讨论】:

有一个 POD 可以满足您的需求。此 POD 在社区中广为人知,易于使用并被大量应用程序使用。它是麻省理工学院的许可证。我觉得你应该试试。 MBProgressHUD 事实上,我正在尝试这样做,因为我们正在远离 MBProgressHUD。它在我们的应用程序中太小了,并且没有阻止用户输入或提供取消按钮等功能。 【参考方案1】:

就像这里提到的JonasG,有一个名为contentViewController的属性,我们可以使用KVC进行访问

示例:

UIViewController *v = [[UIViewController alloc] init];
v.view.backgroundColor = [UIColor redColor];

[alertController setValue:v forKey:@"contentViewController"];

这就是您的代码应该是什么样子(经过测试并且工作正常):

- (IBAction)buttonClicked:(id)sender


    self.alertController = [UIAlertController alertControllerWithTitle: @"Loading"
                                                           message: nil
                                                    preferredStyle: UIAlertControllerStyleAlert];


    [self.alertController addAction:[UIAlertAction actionWithTitle: @"Cancel" style: UIAlertActionStyleCancel handler:nil]];


    UIViewController *customVC     = [[UIViewController alloc] init];


    UIActivityIndicatorView* spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [spinner startAnimating];
    [customVC.view addSubview:spinner];


    [customVC.view addConstraint:[NSLayoutConstraint
                           constraintWithItem: spinner
                           attribute:NSLayoutAttributeCenterX
                           relatedBy:NSLayoutRelationEqual
                           toItem:customVC.view
                           attribute:NSLayoutAttributeCenterX
                           multiplier:1.0f
                           constant:0.0f]];



    [customVC.view addConstraint:[NSLayoutConstraint
                           constraintWithItem: spinner
                           attribute:NSLayoutAttributeCenterY
                           relatedBy:NSLayoutRelationEqual
                           toItem:customVC.view
                           attribute:NSLayoutAttributeCenterY
                           multiplier:1.0f
                           constant:0.0f]];


    [self.alertController setValue:customVC forKey:@"contentViewController"];


    [self presentViewController: self.alertController
                         animated: true
                       completion: nil];


您可以覆盖 -preferredContentSize 以在 您设置为 contentViewController 的视图控制器。

在我们的例子中是customVC

结果:

希望文本位于指标下方?

我已经创建了一个UIViewController 和一个xib 作为我们contentViewController 的自定义控制器在第一个示例中我们创建了没有xib 文件的视图控制器,现在我们可以使用界面生成器添加视图,我已经添加了一个活动指示器并将约束设置为水平和垂直居中,并且水平居中的活动指示器下方的标签是我的界面构建器:

我们现在的代码更少了:

- (IBAction)buttonClicked:(id)sender


    self.alertController = [UIAlertController alertControllerWithTitle: nil
                                                           message: nil
                                                    preferredStyle: UIAlertControllerStyleAlert];

    MyCustomViewController *v     = [[MyCustomViewController alloc] init];

    [self.alertController setValue:v forKey:@"contentViewController"];
    [self presentViewController: self.alertController animated: true  completion: nil];


结果:

【讨论】:

谢谢!当它回到我的队列时我会试试这个 好吧,它现在漂亮地位于白色矩形内,但位于底部。如何把它放在文字上方? 此外,即使在设置preferredContentSize 谢谢你,漂亮!我将在我的新设计中使用它 是的,正如您从代码中看到的那样,我删除了 addAction 行只是为了设计目的;)

以上是关于如何将 UIActivityIndi​​catorView 放在 UIAlertController 中?的主要内容,如果未能解决你的问题,请参考以下文章

将 UIActivityIndi​​cator 添加到模态视图 (ELCimagepicker)

将 UIActivityIndi​​cator 添加到 UITableView

UISearchBar在Swift中完成后如何停止UIActivityIndi​​cator

按下时如何使 UIButton 收缩为 UIActivityIndi​​cator?

在 UIButton 中放置一个 UIActivityIndi​​cator

处理 UIActivityIndi​​cator 和多线程的最佳方法是啥?