Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 966
zyxel Avatar asked Oct 17 '13 15:10

zyxel


2 Answers

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 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)          */     }  } 

2. UIViewAutoresizing style

Springs 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         ]     }  } 

3. Visual Format Language style

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)     }  } 

4. 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)          */     }  } 
like image 78
Imanou Petit Avatar answered Sep 19 '22 18:09

Imanou Petit


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 :)

like image 25
tarmes Avatar answered Sep 19 '22 18:09

tarmes