使用可视格式语言在其超级视图中居中视图

时间:2012-10-13 13:03:02

标签: ios layout autolayout visual-format-language

我刚刚开始学习iOS的AutoLayout,并看了一下Visual Format Language。

除了一件事以外,一切正常:我无法在超视图中找到中心的视图 这可能与VFL有关,还是我需要自己手动创建一个约束?

14 个答案:

答案 0 :(得分:225)

目前,不,它看起来不像使用 VFL将视图置于超级视图中心。然而,使用单个VFL字符串和单个额外约束(每个轴)并不困难:

VFL:"|-(>=20)-[view]-(>=20)-|"

[NSLayoutConstraint constraintWithItem:view
                             attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                                toItem:view.superview
                             attribute:NSLayoutAttributeCenterX
                            multiplier:1.f constant:0.f];

有人会认为你只能做到这一点(这是我在看到这个问题时最初的想法和尝试):

[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=20)-[view(==200)]-(>=20)-|"
                                 options: NSLayoutFormatAlignAllCenterX | NSLayoutFormatAlignAllCenterY
                                 metrics:nil
                                   views:@{@"view" : view}];

我尝试了上面的许多不同变体尝试将其弯曲到我的意愿,但即使明确地为两个轴(H:|V:)明确地具有两个单独的VFL字符串,这似乎也不适用于超视图。然后我开始尝试准确地隔离选项应用于VFL。它们似乎适用于VFL中的超级视图,并且仅适用于VFL字符串中提到的任何显式视图(在某些情况下令人失望)。

我希望将来Apple增加了一些新的选项,让VFL选项考虑到superview,即使只在VFL中的superview之外只有一个显式视图时这样做。另一个解决方案可能是传入VFL的另一个选项,例如:NSLayoutFormatOptionIncludeSuperview

毋庸置疑,我学到了很多关于VFL试图回答这个问题的知识。

答案 1 :(得分:136)

是的,可以使用Visual Format Language将视图置于其超视图中心。垂直和水平。这是演示:

https://github.com/evgenyneu/center-vfl

答案 2 :(得分:82)

我认为手动创建约束会更好。

[superview addConstraint:
 [NSLayoutConstraint constraintWithItem:view
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:superview
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];
[superview addConstraint:
 [NSLayoutConstraint constraintWithItem:view
                              attribute:NSLayoutAttributeCenterY
                              relatedBy:NSLayoutRelationEqual
                                 toItem:superview
                              attribute:NSLayoutAttributeCenterY
                             multiplier:1
                               constant:0]];

现在我们可以使用NSLayoutAnchor以编程方式定义AutoLayout:

(适用于iOS 9.0及更高版本)

view.centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true
view.centerYAnchor.constraint(equalTo: superview.centerYAnchor).isActive = true

我建议使用SnapKit,这是一个DSL,可以在iOS和macOS上轻松实现自动布局。

view.snp.makeConstraints({ $0.center.equalToSuperview() })

答案 3 :(得分:10)

绝对有可能这样做:

[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]"
                                        options:NSLayoutFormatAlignAllCenterY
                                        metrics:nil
                                          views:NSDictionaryOfVariableBindings(view, subview)];

here.了解到这一点 上面的代码明显是Y中的子视图。

Swift3:

        NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=1)-[subview]",
                                       options: .alignAllCenterY,
                                                       metrics: nil,
                                                       views: ["view":self, "subview":_spinnerView])

答案 4 :(得分:7)

添加以下代码,并将按钮置于屏幕中央。绝对可能。

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-[button]-|"
                           options:NSLayoutFormatAlignAllCenterY
                           metrics:0
                           views:views]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[button]-|"
                           options:NSLayoutFormatAlignAllCenterX
                           metrics:0
                           views:views]];

答案 5 :(得分:1)

我知道这不是你想要的,但你当然可以计算边距并使用它们来创建可视化格式字符串;)

无论如何,没有。不幸的是,用VFL“自动”做到这一点是不可能的 - 至少现在还没有。

答案 6 :(得分:1)

感谢@Evgenii的回答,我在gist中创建了一个完整的例子:

center the red square vertically with custom height

https://gist.github.com/yallenh/9fc2104b719742ae51384ed95dcaf626

您可以使用VFL(不太直观)或手动使用约束来垂直居中。 顺便说一句,我不能在VFL中将centerY和height结合在一起,如:

"H:[subView]-(<=1)-[followIcon(==customHeight)]"

在当前的解决方案中,VFL约束是单独添加的。

答案 7 :(得分:0)

必须要做的是superview应该在字典中声明。您没有使用|,而是使用@{@"super": view.superview};

纵向为NSLayoutFormatAlignAllCenterX,横向为NSLayoutFormatAlignAllCenterY

答案 8 :(得分:0)

您可以使用额外的观看次数。

NSDictionary *formats =
@{
  @"H:|[centerXView]|": @0,
  @"V:|[centerYView]|": @0,
  @"H:[centerYView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterY),
  @"V:[centerXView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterX),
};
NSDictionary *views = @{
  @"centerXView": centerXView, 
  @"centerYView": centerYView, 
  @"yourView": yourView,
};
 ^(NSString *format, NSNumber *options, BOOL *stop) {
     [superview addConstraints:
      [NSLayoutConstraint constraintsWithVisualFormat:format
                                              options:options.integerValue
                                              metrics:nil
                                                views:views]];
 }];

如果你想要它整洁,那么centerXView.hidden = centerYView.hidden = YES;

PS:我不确定我可以将额外的观点称为“占位符”,因为英语是我的第二语言。如果有人能告诉我,我们将不胜感激。

答案 9 :(得分:0)

对于那些来这里寻找Interface Builder解决方案的人(Google引导我),只需添加const宽度/高度限制,然后选择子视图 - &gt;控制拖动到它的超级视图 - &gt;选择“在superview中垂直/水平居中”。

答案 10 :(得分:0)

这是我的方法

//create a 100*100 rect in the center of superView
var consts = NSLayoutConstraint.constraints(withVisualFormat: "H:|-space-[myView]-space-|", options: [], metrics:["space":view.bounds.width/2-50], views:["myView":myView])

consts += NSLayoutConstraint.constraints(withVisualFormat: "V:|-space-[myView]-space-|", options: [], metrics: ["space":view.bounds.height/2-50], views: ["myView":myView])

答案 11 :(得分:-1)

只需要说,你可以使用它代替约束:

child.center = [parent convertPoint:parent.center fromView:parent.superview];

答案 12 :(得分:-1)

Swift 2

@ igor-muzyka 回答:

NSLayoutConstraint.constraintsWithVisualFormat("H:[view]-(<=1)-[subview]", 
                                               options: .AlignAllCenterY,
                                               metrics: nil,
                                               views: ["view":view, "subview":subview])

答案 13 :(得分:-3)

您可以在界面构建器中轻松执行此操作,而不是使用VFL。在主故事板中,按住Ctrl键并单击要居中的视图。拖动到超级视图(按住ctrl)并选择“中心X”或“中心Y”。无需代码。