如何使用自动布局以编程方式将活动指示器定位到其超级视图的中心



为什么以下代码不适用于将活动指示器定位到其超级视图的中心:

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

活动指示器位于左上角的某个地方,绝对不在中心。

==================

更新:找到的解决方案:我必须在创建指标后关闭自动调整大小约束,然后关闭所有给定的解决方案:

 [activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO];

我在@Vignesh给出的链接上找到了它,所以我接受他/她的回答。

以下四个 Swift 5/iOS 12 代码示例展示了如何使用自动布局UIActivityIndicatorView居中置于UIViewController UIView内。

所有样品产生相同的结果,但根据您的需求和口味,您可以选择其中一种。

如果你UIActivityIndicatorView的超级视图不是self.view,你只需要用你自己的(解开包装的)superview替换每个self.view调用。

<小时 />

1. NSLayoutConstraint初始值设定项样式

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风格

弹簧和支柱将在运行时转换为相应的自动布局约束。

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. 视觉格式语言风格

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风格(需要 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)
         */
    }
}
它通过

处于角落来满足它的要求,因为你并不是说每边的间隙必须相同。 试试这个:

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

要垂直居中,也要这样做:

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

或者,我强烈建议使用 FLKAutoLayout 项目来简化所有这些:

https://github.com/dkduck/FLKAutoLayout

然后你可以做:

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

这是一个很好的:)

你可以

试试这个,

 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];

取自这里。

我通过将

活动指标添加到界面生成器中,alpha 为零(在我的视图控制器类中为它的 IBOutlet)将活动指标居中。 然后,我添加了约束以使其在 X 轴和 Y 轴上居中。 最后,我为其添加了宽度和高度约束,以消除自动布局错误。

在我的视图控制器的 startActivityIndicator 方法中,我将活动指示器的 alpha 设置为 1,并对其调用 startAnimating 方法。 在我的 stopActivityIndicator 方法中,我对其调用 stopAnimating 方法,并将活动指标的 alpha 设置回零。

最新更新