I used to have a "Please wait" dialog in my app for long time. It was quite simple thing using UIActivityIndicatorView
and adding it to UIAlertView
.
However iOS8 introduced UIAlertController
. Is it possible to add anything to it to have similiar effect? Is there another way of doing such thing with iOS8?
I have searched a lot of sites and still have no idea how it can be done with the new API.
I would appreciate any answers - links to libs, tutorials etc., which could be helpful.
Regards,
Mateusz
Instead of using a UIAlertController, you can use a custom UIViewController that is presented modally. Here is what I use in 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))
}
}
You use it like this:
let activitiyViewController = ActivityViewController(message: "Loading...")
presentViewController(activitiyViewController, animated: true, completion: nil)
And it will look like this:
See this answer for a sample implementation that recreates the UIAlertController
animation using UIViewControllerAnimatedTransitioning
.