Answers:
当前,不,看起来仅使用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字符串提到任何明确的意见。
我希望将来苹果可以添加某种新选项,使VFL选项考虑到超级视图,即使仅在VFL中除了超级视图之外只有一个显式视图时也可以这样做。另一个解决方案可能是传递到VFL中的另一个选项,内容类似于:NSLayoutFormatOptionIncludeSuperview
。
不用说,我了解了很多有关VFL试图回答这个问题的知识。
|
,[superview]
是因为自动布局引擎将和视为独立的内部实体,即使它们表示相同的语义对象。通过使用[superview]
,自动布局会将Superview对象包含在其对齐度量标准中(在github链接中,他的答案是NSLayoutFormatAlignAllCenterY
/ X
度量标准)。
是的,可以使用Visual Format Language在其超级视图中居中视图。垂直和水平方向。这是演示:
我认为最好手动创建约束。
[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() })
Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead.
绝对有可能做到这一点:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:NSDictionaryOfVariableBindings(view, subview)];
Swift3:
NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=1)-[subview]",
options: .alignAllCenterY,
metrics: nil,
views: ["view":self, "subview":_spinnerView])
添加以下代码,并将您的按钮放在屏幕中心。绝对有可能。
[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]];
我知道这不是您想要的,但是您当然可以计算出边距并使用它们创建视觉格式字符串;)
反正不行 不幸的是,使用VFL无法“自动”执行此操作-至少现在还没有。
感谢@Evgenii的回答,我在gist中创建了一个完整的示例:
https://gist.github.com/yallenh/9fc2104b719742ae51384ed95dcaf626
您可以使用VFL(不太直观)或手动使用约束来垂直放置视图中心。顺便说一句,我不能像这样在VFL中将centerY和height结合在一起:
"H:[subView]-(<=1)-[followIcon(==customHeight)]"
在当前解决方案中,VFL约束是单独添加的。
您可以使用其他视图。
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:我不确定我是否可以将额外的视图称为“占位符”,因为英语是我的第二语言。如果有人可以告诉我,将不胜感激。
对于那些来这里寻求Interface Builder
基础解决方案的人(Google在这里领先我),只需添加const宽度/高度约束,然后选择子视图->将控件拖动到其超级视图->选择“在超级视图中垂直/水平居中”。
//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])
只需说,您可以使用它代替约束:
child.center = [parent convertPoint:parent.center fromView:parent.superview];