使用可视格式NSLayoutConstraints对中视图

Jos*_*eph 22 objective-c autolayout nslayoutconstraint ios7

我试图使用可视化格式语言来居中视图.

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView(300)]-|" options:NSLayoutFormatAlignAllCenterY metrics:0 views:views]];
Run Code Online (Sandbox Code Playgroud)

(views是一个NSDictionaryOfVariableBindings包含_progressView)

它不会将我的视图(宽度:300)置于self.view(宽度:768)内.它将它与8像素边距对齐,好像我只会写@"H:|-[_progressView(300)".

是使用类似的东西来中心视图的唯一方法:?

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_progressView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
Run Code Online (Sandbox Code Playgroud)

谢谢

Dru*_*erB 34

这种格式字符串

@"H:|-[_progressView(300)]-|"
Run Code Online (Sandbox Code Playgroud)

不会告诉AutoLayout居中progressView.相反,它说progressView应该是300宽,并且在超视图边缘的两侧都有一个系统定义的标准边距.显然这不能满足,因此Auto Layout会删除一些约束(您可能会在控制台上获得一些日志).在您的情况下丢弃的约束可能是右侧的边距.

要真正将视图置于其超级视图中,您必须使用详细约束方法而不是可视字符串格式,正如您已经想到的那样.但是,您可以轻松地将其放入这样一个很好的类别中:

@interface UIView (MyLayout)
- (void)centerHorizontallyInSuperview;
@end

@implementation UIView (MyLayout)
- (void)centerHorizontallyInSuperview {
    NSLayoutConstraint *c;
    c = [NSLayoutConstraint constraintWithItem:self
                                     attribute:NSLayoutAttributeCenterX
                                     relatedBy:NSLayoutRelationEqual                                                             
                                        toItem:self.superview
                                     attribute:NSLayoutAttributeCenterX 
                                    multiplier:1 
                                      constant:0];
    [self.superview addConstraint:c];
}
@end
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 17

三种方法:

  1. 您可以根据DrummerB的建议将约束添加到方法或类别中.

    你也是有效的iOS 9,可以使用更新,更简洁的语法,使用锚点和使用activateConstraints:

    [NSLayoutConstraint activateConstraints:@[
        [centerView.centerXAnchor constraintEqualToAnchor:view.centerXAnchor],
        ...
    ]];
    
    Run Code Online (Sandbox Code Playgroud)

    或者在Swift 3中:

    NSLayoutConstraint.activate([
        centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        ...
    ])
    
    Run Code Online (Sandbox Code Playgroud)
  2. 你可以使用UILayoutGuide对象:

    UILayoutGuide *leftGuide = [[UILayoutGuide alloc] init];
    [view addLayoutGuide:leftGuide];
    UILayoutGuide *rightGuide = [[UILayoutGuide alloc] init];
    [view addLayoutGuide:rightGuide];
    
    Run Code Online (Sandbox Code Playgroud)

    并使用VFL将它们定义为彼此相等:

    H:|[leftGuide][_progressView(==300)][rightGuide(==leftGuide)]|
    
    Run Code Online (Sandbox Code Playgroud)

    如果你不能使用布局指南(例如你需要支持9.0之前的iOS版本,你想在IB中创建它等),你可以使用不可见的UIView对象(零的alpha或透明的背景颜色)非常相似的方式.只需将这些"spacer"视图添加到视图层次结构中,使用上面的水平约束,但只需配置视图就可以看不到它们.

    这种技术是解决"视图中心如何"问题的一种麻烦的方法,但是如果你想要均匀地分隔十几个视图并且UIStackView由于某种原因你不能使用a ,那么它非常有用.您可以使用所需的许多UILayoutGuide(或不可见UIView)对象以获得所需的效果.

  3. 为了完整起见,我应该指出,它可能通过使用来达到效果optionsNSLayoutFormatAlignAllCenterX/ Y,简列如/sf/answers/1044238681/,但我承认,我觉得不必要的混乱.

就个人而言,我认为第一种方法对您的场景最有意义.第二种方法在尝试均匀分布一堆控件时很有用,但对于这种简单的场景来说太笨拙了.第三种方法是求知欲,但我不会在任何实际应用中提出建议.


Koe*_*en. 7

对于那些需要它的人,@ DrummerB的ObjC类别为Swift扩展:

extension UIView {

    func centerInSuperview() {
        self.centerHorizontallyInSuperview()
        self.centerVerticallyInSuperview()
    }

    func centerHorizontallyInSuperview(){
        let c: NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: .CenterX, relatedBy: .Equal, toItem: self.superview, attribute: .CenterX, multiplier: 1, constant: 0)
        self.superview?.addConstraint(c)
    }

    func centerVerticallyInSuperview(){
        let c: NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: .CenterY, relatedBy: .Equal, toItem: self.superview, attribute: .CenterY, multiplier: 1, constant: 0)
        self.superview?.addConstraint(c)
    }

}
Run Code Online (Sandbox Code Playgroud)