Why the following code does not work for positioning activity indicator to the center of its superview:
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; [self.mysuperview addSubview:activityIndicator]; [activityIndicator addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=20)-[view(==100)]-(>=20)-|" options:NSLayoutFormatAlignAllCenterX | NSLayoutFormatAlignAllCenterY metrics:nil views:@{@"view" : self.mysuperview}]];
Activity indicator is positioned somewhere at the top left corner, definitely not in the centre.
================== Update: FOUND SOLUTION: I have to turn off autoresizing constraints after creating indicator and then all solutions that where given work:
[activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO];
I found it on the link given by @Vignesh, so I accept his/her answer.
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
.
NSLayoutConstraint
initializer styleimport UIKit class 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) */ } }
UIViewAutoresizing
styleSprings and Struts will be translated into corresponding auto layout constraints at runtime.
import UIKit class 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 ] } }
import UIKit class 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) } }
NSLayoutAnchor
style (requires iOS 9)import UIKit class 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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With