ios 使用 Visual Format Language 将视图居中在其父视图中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12873372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:44:23  来源:igfitidea点击:

Centering a view in its superview using Visual Format Language

ioslayoutautolayoutvisual-format-language

提问by Christian Schnorr

I just started learning AutoLayout for iOS and had a look at Visual Format Language.

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

It all works fine except for one thing: I just can't get a view to center within its superview.
Is this possible with VFL or do I need to manually create a constraint myself?

除了一件事之外,一切都很好:我只是无法将视图置于其超级视图的中心。
这对 VFL 是可能的还是我需要自己手动创建约束?

回答by larsacus

Currently, no, it doesn't look like it is possible to center a view in the superview using onlyVFL. It is, however, not that difficult to do it using a single VFL string and a single extra constraint (per axis):

目前,不,看起来不可能使用VFL将视图在超级视图中居中。但是,使用单个 VFL 字符串和单个额外约束(每个轴)来做到这一点并不难:

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

视觉效果: "|-(>=20)-[view]-(>=20)-|"

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

One would think that you would simply be able to do this (which is what I initially thought and tried when I saw this question):

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

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

I tried many different variations of the above trying to bend it to my will, but this does not appear to apply to the superview even when explicitly having two separate VFL strings for both axes (H:|V:). I then started to try and isolate exactly when the options doget applied to the VFL. They appear to notapply to the superview in the VFL and will only apply to any explicit views that are mentioned in the VFL string (which is disappointing in certain cases).

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

I hope in the future Apple adds some kind of new option to have the VFL options take into account the superview, even if doing it only when there is only a single explicit view besides the superview in the VFL. Another solution could be another option passed into the VFL that says something like: NSLayoutFormatOptionIncludeSuperview.

我希望将来 Apple 添加某种新选项以使 VFL 选项考虑到超级视图,即使仅在 VFL 中的超级视图之外只有一个显式视图时才这样做。另一种解决办法是传递到VFL另一种选择,说是这样的:NSLayoutFormatOptionIncludeSuperview

Needless to say, I learned a lot about VFL trying to answer this question.

不用说,我在尝试回答这个问题时学到了很多关于 VFL 的知识。

回答by Evgenii

Yes, it is possible to center a view in its superview with Visual Format Language. Both vertically and horizontally. Here is the demo:

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

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

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

回答by jqgsninimo

I think it is better to manually create constraints.

我认为最好手动创建约束。

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


Now we can use NSLayoutAnchorto programatically define AutoLayout:

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

(Available in iOS 9.0 and later)

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

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


I recommend using SnapKit, which is a DSL to make Auto Layout easy on both iOS and macOS.

我推荐使用SnapKit,它是一种 DSL,可以在 iOS 和 macOS 上轻松实现自动布局。

view.snp.makeConstraints({ 
[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]"
                                        options:NSLayoutFormatAlignAllCenterY
                                        metrics:nil
                                          views:NSDictionaryOfVariableBindings(view, subview)];
.center.equalToSuperview() })

回答by Igor Muzyka

Absolutely possible was able to do it like this:

绝对有可能这样做:

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

Learned this from here.Code above centers subview in view by Y obviously.

这里学到了这一点。上面的代码显然在 Y 的视图中居中子视图。

Swift3:

斯威夫特3:

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

回答by Pankaj Gaikar

Add below code and have your button at the center of the screen. Absolutely possible.

添加以下代码并将您的按钮放在屏幕中央。绝对有可能。

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

回答by Allen Huang

Thanks to the answer from @Evgenii, I create a full example in gist:

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

center the red square vertically with custom height

以自定义高度垂直居中红色方块

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

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

You can center a view vertically by useing either VFL (which is not quite intuitive) or use constraints manually. By the way, I cannot combine both centerY and height together in VFL like:

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

//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])

In the current solution VFL constraints are added separately.

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

回答by Tobi

I know it's not want you want but you can of course calculate the margins and use them to create the visual format string ;)

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

Anyway, no. Unfortunatly it's not possible to do that 'automatically' with VFL - at least not yet.

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

回答by Calcifer

This is my method

这是我的方法

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

回答by lagos

What it have to be done is that superview should be declared in the dictionary. Instead of using |you use @{@"super": view.superview};.

需要做的是在字典中声明superview。而不是使用|你使用@{@"super": view.superview};.

And NSLayoutFormatAlignAllCenterXfor vertical and NSLayoutFormatAlignAllCenterYfor horizontal as options.

NSLayoutFormatAlignAllCenterX对于垂直和NSLayoutFormatAlignAllCenterY用于水平作为选择。

回答by CopperCash

You can use extra views.

您可以使用额外的视图。

##代码##

If you want it neat, then centerXView.hidden = centerYView.hidden = YES;.

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

PS: I am not sure I can call the extra views "placeholders", because English is my second language. It will be appreciated if someone can tell me that.

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