我曾经在我的应用程序中有一个“请稍候”对话框很长一段时间。使用UIActivityIndicatorView
并将其添加到UIAlertView
.
不过 iOS8 引入了UIAlertController
. 是否可以添加任何东西以产生类似的效果?有没有另一种方法可以用 iOS8 做这样的事情?
我搜索了很多网站,但仍然不知道如何使用新的 API 来完成。
我将不胜感激 - 指向库、教程等的链接,这可能会有所帮助。
问候,
马特乌什
我曾经在我的应用程序中有一个“请稍候”对话框很长一段时间。使用UIActivityIndicatorView
并将其添加到UIAlertView
.
不过 iOS8 引入了UIAlertController
. 是否可以添加任何东西以产生类似的效果?有没有另一种方法可以用 iOS8 做这样的事情?
我搜索了很多网站,但仍然不知道如何使用新的 API 来完成。
我将不胜感激 - 指向库、教程等的链接,这可能会有所帮助。
问候,
马特乌什
您可以使用模态显示的自定义 UIViewController,而不是使用 UIAlertController。这是我在 Swift 2.0 中使用的:
class ActivityViewController: UIViewController {
private let activityView = ActivityView()
init(message: String) {
super.init(nibName: nil, bundle: nil)
modalTransitionStyle = .CrossDissolve
modalPresentationStyle = .OverFullScreen
activityView.messageLabel.text = message
view = activityView
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
private class ActivityView: UIView {
let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
let boundingBoxView = UIView(frame: CGRectZero)
let messageLabel = UILabel(frame: CGRectZero)
init() {
super.init(frame: CGRectZero)
backgroundColor = UIColor(white: 0.0, alpha: 0.5)
boundingBoxView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
boundingBoxView.layer.cornerRadius = 12.0
activityIndicatorView.startAnimating()
messageLabel.font = UIFont.boldSystemFontOfSize(UIFont.labelFontSize())
messageLabel.textColor = UIColor.whiteColor()
messageLabel.textAlignment = .Center
messageLabel.shadowColor = UIColor.blackColor()
messageLabel.shadowOffset = CGSizeMake(0.0, 1.0)
messageLabel.numberOfLines = 0
addSubview(boundingBoxView)
addSubview(activityIndicatorView)
addSubview(messageLabel)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
boundingBoxView.frame.size.width = 160.0
boundingBoxView.frame.size.height = 160.0
boundingBoxView.frame.origin.x = ceil((bounds.width / 2.0) - (boundingBoxView.frame.width / 2.0))
boundingBoxView.frame.origin.y = ceil((bounds.height / 2.0) - (boundingBoxView.frame.height / 2.0))
activityIndicatorView.frame.origin.x = ceil((bounds.width / 2.0) - (activityIndicatorView.frame.width / 2.0))
activityIndicatorView.frame.origin.y = ceil((bounds.height / 2.0) - (activityIndicatorView.frame.height / 2.0))
let messageLabelSize = messageLabel.sizeThatFits(CGSizeMake(160.0 - 20.0 * 2.0, CGFloat.max))
messageLabel.frame.size.width = messageLabelSize.width
messageLabel.frame.size.height = messageLabelSize.height
messageLabel.frame.origin.x = ceil((bounds.width / 2.0) - (messageLabel.frame.width / 2.0))
messageLabel.frame.origin.y = ceil(activityIndicatorView.frame.origin.y + activityIndicatorView.frame.size.height + ((boundingBoxView.frame.height - activityIndicatorView.frame.height) / 4.0) - (messageLabel.frame.height / 2.0))
}
}
你像这样使用它:
let activitiyViewController = ActivityViewController(message: "Loading...")
presentViewController(activitiyViewController, animated: true, completion: nil)
它看起来像这样:
有关使用. _ UIAlertController
_UIViewControllerAnimatedTransitioning
试试这个我做了一些技巧......
下面的代码在 iPod iOS8beta5 + XCode6 中为我工作
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
message:@"Please wait\n\n\n"
preferredStyle:UIAlertControllerStyleAlert];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(130.5, 65.5);
spinner.color = [UIColor blackColor];
[spinner startAnimating];
[alert.view addSubview:spinner];
[self presentViewController:alert animated:NO completion:nil];
斯威夫特 3.0/4.1
要显示进度对话框:
let alertController = UIAlertController(title: nil, message: "Please wait\n\n", preferredStyle: .alert)
let spinnerIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
spinnerIndicator.center = CGPoint(x: 135.0, y: 65.5)
spinnerIndicator.color = UIColor.black
spinnerIndicator.startAnimating()
alertController.view.addSubview(spinnerIndicator)
self.present(alertController, animated: false, completion: nil)
要关闭进度对话框:
alertController.dismiss(animated: true, completion: nil);
斯威夫特 2.0:
override func viewDidAppear(animated: Bool)
{
let alertController = UIAlertController(title: nil, message: "Please wait\n\n", preferredStyle: UIAlertControllerStyle.Alert)
let spinnerIndicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
spinnerIndicator.center = CGPointMake(135.0, 65.5)
spinnerIndicator.color = UIColor.blackColor()
spinnerIndicator.startAnimating()
alertController.view.addSubview(spinnerIndicator)
self.presentViewController(alertController, animated: false, completion: nil)
}
过了一段时间,我们需要隐藏警报。
alertController.dismissViewControllerAnimated(true, completion: nil)
如果您只想显示标题和活动指示器并且您喜欢冒险,您可以破解 AlertController 的视图层次结构。下面的代码适用于 8.2。然而,这通常不应该在生产中。
正如在下面的评论中指出的那样,在您的应用程序中使用此代码可能会被拒绝,以下是文档的摘录:
UIAlertController 类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。
@implementation AlertControllerWithActivityIndicator
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIView *scrollView = [self findViewByClassPrefix:@"_UIAlertControllerShadowedScrollView" inView:self.view];
UIView *containerView = [scrollView.subviews firstObject];
UILabel *titleLabel = containerView.subviews.firstObject;
if(!titleLabel) {
return;
}
if(!self.indicatorView) {
self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.indicatorView.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:self.indicatorView];
NSDictionary *views = @{ @"text": titleLabel, @"indicator": self.indicatorView };
NSArray *constraints = [scrollView constraintsAffectingLayoutForAxis:UILayoutConstraintAxisVertical];
for(NSLayoutConstraint *constraint in constraints) {
if(constraint.firstItem == containerView && constraint.secondItem == titleLabel && constraint.firstAttribute == NSLayoutAttributeBottom) {
constraint.active = NO;
}
}
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[text]-[indicator]-24-|" options:0 metrics:nil views:views]];
[containerView addConstraint:[NSLayoutConstraint constraintWithItem:self.indicatorView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
[self.indicatorView startAnimating];
}
}
- (UIView *)findViewByClassPrefix:(NSString *)prefix inView:(UIView *)view {
for(UIView *subview in view.subviews) {
if([NSStringFromClass(subview.class) hasPrefix:prefix]) {
return subview;
}
UIView *child = [self findViewByClassPrefix:prefix inView:subview];
if(child) {
return child;
}
}
return nil;
}
@end
产生类似的东西:
与@pheedsta 相同,但改为使用 Swift 4
import UIKit
class ActivityViewController: UIViewController {
private let activityView = ActivityView()
init(message: String) {
super.init(nibName: nil, bundle: nil)
modalTransitionStyle = .crossDissolve
modalPresentationStyle = .overFullScreen
activityView.messageLabel.text = message
view = activityView
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
private class ActivityView: UIView {
let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
let boundingBoxView = UIView(frame: CGRect.zero)
let messageLabel = UILabel(frame: CGRect.zero)
init() {
super.init(frame: CGRect.zero)
backgroundColor = UIColor(white: 0.0, alpha: 0.5)
boundingBoxView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
boundingBoxView.layer.cornerRadius = 12.0
activityIndicatorView.startAnimating()
messageLabel.font = UIFont.boldSystemFont(ofSize: UIFont.labelFontSize)
messageLabel.textColor = UIColor.white
messageLabel.textAlignment = .center
messageLabel.shadowColor = UIColor.black
messageLabel.shadowOffset = CGSize(width: 0.0, height: 1.0)
messageLabel.numberOfLines = 0
addSubview(boundingBoxView)
addSubview(activityIndicatorView)
addSubview(messageLabel)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
boundingBoxView.frame.size.width = 160.0
boundingBoxView.frame.size.height = 160.0
boundingBoxView.frame.origin.x = ceil((bounds.width / 2.0) - (boundingBoxView.frame.width / 2.0))
boundingBoxView.frame.origin.y = ceil((bounds.height / 2.0) - (boundingBoxView.frame.height / 2.0))
activityIndicatorView.frame.origin.x = ceil((bounds.width / 2.0) - (activityIndicatorView.frame.width / 2.0))
activityIndicatorView.frame.origin.y = ceil((bounds.height / 2.0) - (activityIndicatorView.frame.height / 2.0))
let messageLabelSize = messageLabel.sizeThatFits(CGSize(width: 160.0 - 20.0 * 2.0, height: CGFloat.greatestFiniteMagnitude))
messageLabel.frame.size.width = messageLabelSize.width
messageLabel.frame.size.height = messageLabelSize.height
messageLabel.frame.origin.x = ceil((bounds.width / 2.0) - (messageLabel.frame.width / 2.0))
messageLabel.frame.origin.y = ceil(activityIndicatorView.frame.origin.y + activityIndicatorView.frame.size.height + ((boundingBoxView.frame.height - activityIndicatorView.frame.height) / 4.0) - (messageLabel.frame.height / 2.0))
}
}
用法:
// Initiate somewhere
let activitiyViewController = ActivityViewController(message: "Loading...")
// To start/show
present(activitiyViewController, animated: true, completion: nil)
// To stop/dissmiss
activitiyViewController.dismiss(animated: true)
仅使用基本 API 似乎不可能以普通的方式完成。我决定使用允许进行此类修改的 DTAlertView。它按我的意愿工作。
Swift 3.1 版本的@darksinge 代码
import UIKit
class ActivityViewController: UIViewController {
private let activityView = ActivityView()
init(message: String) {
super.init(nibName: nil, bundle: nil)
modalTransitionStyle = .crossDissolve
modalPresentationStyle = .overFullScreen
activityView.messageLabel.text = message
view = activityView
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
private class ActivityView: UIView {
let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
let boundingBoxView = UIView(frame: CGRect.zero)
let messageLabel = UILabel(frame: CGRect.zero)
init() {
super.init(frame: CGRect.zero)
backgroundColor = UIColor(white: 0.0, alpha: 0.5)
boundingBoxView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
boundingBoxView.layer.cornerRadius = 12.0
activityIndicatorView.startAnimating()
messageLabel.font = UIFont.boldSystemFont(ofSize: UIFont.labelFontSize)
messageLabel.textColor = UIColor.white
messageLabel.textAlignment = .center
messageLabel.shadowColor = UIColor.black
messageLabel.shadowOffset = CGSize(width: 0.0, height: 1.0)
messageLabel.numberOfLines = 0
addSubview(boundingBoxView)
addSubview(activityIndicatorView)
addSubview(messageLabel)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
boundingBoxView.frame.size.width = 160.0
boundingBoxView.frame.size.height = 160.0
boundingBoxView.frame.origin.x = ceil((bounds.width / 2.0) - (boundingBoxView.frame.width / 2.0))
boundingBoxView.frame.origin.y = ceil((bounds.height / 2.0) - (boundingBoxView.frame.height / 2.0))
activityIndicatorView.frame.origin.x = ceil((bounds.width / 2.0) - (activityIndicatorView.frame.width / 2.0))
activityIndicatorView.frame.origin.y = ceil((bounds.height / 2.0) - (activityIndicatorView.frame.height / 2.0))
let messageLabelSize = messageLabel.sizeThatFits(CGSize(width:160.0 - 20.0 * 2.0, height: CGFloat.greatestFiniteMagnitude))
messageLabel.frame.size.width = messageLabelSize.width
messageLabel.frame.size.height = messageLabelSize.height
messageLabel.frame.origin.x = ceil((bounds.width / 2.0) - (messageLabel.frame.width / 2.0))
messageLabel.frame.origin.y = ceil(activityIndicatorView.frame.origin.y + activityIndicatorView.frame.size.height + ((boundingBoxView.frame.height - activityIndicatorView.frame.height) / 4.0) - (messageLabel.frame.height / 2.0))
}
}