How to position activity indicator to the center of its superview using Auto Layout programmatically? How to position activity indicator to the center of its superview using Auto Layout programmatically? ios ios

How to position activity indicator to the center of its superview using Auto Layout programmatically?


The four following Swift 5 / iOS 12 code samples show how to center a UIActivityIndicatorView inside the UIView of a UIViewController with Auto layout.

All samples produce the same result but, according to your needs and tastes, you may choose one or the other.

If your UIActivityIndicatorView's superview is not self.view, you simply have to replace each self.view call with your own (unwrapped) superview.


1. NSLayoutConstraint initializer style

import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()        let indicatorView = UIActivityIndicatorView(style: .gray)        indicatorView.isHidden = false        indicatorView.translatesAutoresizingMaskIntoConstraints = false        self.view.addSubview(indicatorView)        // Auto layout        let horizontalConstraint = NSLayoutConstraint(item: indicatorView,                                                      attribute: .centerX,                                                      relatedBy: .equal,                                                      toItem: self.view,                                                      attribute: .centerX,                                                      multiplier: 1,                                                      constant: 0)        let verticalConstraint = NSLayoutConstraint(item: indicatorView,                                                    attribute: .centerY,                                                    relatedBy: .equal,                                                    toItem: self.view,                                                    attribute: .centerY,                                                    multiplier: 1,                                                    constant: 0)        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])        /*         // You can replace NSLayoutConstraint activate(_:) call with the following lines:         self.view.addConstraint(horizontalConstraint)         self.view.addConstraint(verticalConstraint)         */    }}

2. UIViewAutoresizing style

Springs and Struts will be translated into corresponding auto layout constraints at runtime.

import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()        let indicatorView = UIActivityIndicatorView(style: .gray)        indicatorView.isHidden = false        indicatorView.translatesAutoresizingMaskIntoConstraints = true // default is true        self.view.addSubview(indicatorView)        // Springs and struts        indicatorView.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY)        indicatorView.autoresizingMask = [            .flexibleLeftMargin,            .flexibleRightMargin,            .flexibleTopMargin,            .flexibleBottomMargin        ]    }}

3. Visual Format Language style

import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()        let indicatorView = UIActivityIndicatorView(style: .gray)        indicatorView.isHidden = false        indicatorView.translatesAutoresizingMaskIntoConstraints = false        self.view.addSubview(indicatorView)        // Auto layout        let views = ["superview": self.view!, "indicatorView": indicatorView]        let horizontalConstraints = NSLayoutConstraint            .constraints(withVisualFormat: "H:[superview]-(<=0)-[indicatorView]",                         options: .alignAllCenterY,                         metrics: nil,                         views: views)        let verticalConstraints = NSLayoutConstraint            .constraints(withVisualFormat: "V:[superview]-(<=0)-[indicatorView]",                         options: .alignAllCenterX,                         metrics: nil,                         views: views)        self.view.addConstraints(horizontalConstraints)        self.view.addConstraints(verticalConstraints)    }}

4. NSLayoutAnchor style (requires iOS 9)

import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()        let indicatorView = UIActivityIndicatorView(style: .gray)        indicatorView.isHidden = false        indicatorView.translatesAutoresizingMaskIntoConstraints = false        self.view.addSubview(indicatorView)        // Auto layout        let horizontalConstraint = indicatorView            .centerXAnchor.constraint(equalTo: self.view.centerXAnchor)        let verticalConstraint = indicatorView            .centerYAnchor.constraint(equalTo: self.view.centerYAnchor)        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])        /*         // You can replace NSLayoutConstraint activate(_:) call with the following lines:         self.view.addConstraint(horizontalConstraint)         self.view.addConstraint(verticalConstraint)         */    }}


It's meeting it's requirements by being in the corner, since you're not stating that the gaps on each side have to be the same. Try this instead:

[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:activityIndicator               attribute:NSLayoutAttributeCenterX                relatedBy:NSLayoutRelationEqual                   toItem:self.superview                attribute:NSLayoutAttributeCenterX               multiplier:1.0                 constant:0.0]];

And to center vertically do this too:

[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:activityIndicator               attribute:NSLayoutAttributeCenterY                relatedBy:NSLayoutRelationEqual                   toItem:self.superview                attribute:NSLayoutAttributeCenterY               multiplier:1.0                 constant:0.0]];

Alternatively, I highly recommend using the FLKAutoLayout project to simplify all this:

https://github.com/dkduck/FLKAutoLayout

Then you can do:

[activityIndicator alignCenterXWithView:self.superview predicate:nil];[activityIndicator alignCenterYWithView:self.superview predicate:nil];

Which is nice :)


You can try this,

 UIView *superview = self.mysuperview;NSDictionary *variables = NSDictionaryOfVariableBindings(activityIndicator, superview);NSArray *constraints =[NSLayoutConstraint constraintsWithVisualFormat:@"V:[superview]-(<=1)-[activityIndicator]"                                        options: NSLayoutFormatAlignAllCenterX                                        metrics:nil                                          views:variables];[self.view addConstraints:constraints];constraints =[NSLayoutConstraint constraintsWithVisualFormat:@"H:[superview]-(<=1)-[activityIndicator]"                                        options: NSLayoutFormatAlignAllCenterY                                        metrics:nil                                          views:variables];[self.view addConstraints:constraints];

Taken from here.