灵活的宽度约束

Flexible width constraint

我在解决约束方面遇到了困难,也许有人可以提供帮助:

情况如下:

我需要 myView 根据 superview 宽度灵活调整宽度。

如果 superview 的宽度大于 500 -> myView 应该有 500。

如果 superview 的宽度较小,则 500 -> myView 应该占用全部 superView 宽度。

[NSLayoutConstraint constraintsWithVisualFormat:@"[myView(==500)]" options:0 metrics:nil views:@{
    @"myView"    : self.myView,
    @"superview" : superview
}];
// If I write myView(<=500), obviously width will be zero. 
// I can not add something like this:
// @[tableView(<=superview)]", as width can be less, can be more

所以我卡在这里了,有什么想法吗?

提前致谢!

即使按照自动布局标准,视觉格式语言也可能有点不稳定,尤其是在设置优先级时。这个问题实际上是概念性的,可以在 IB 或 VFL 或 class 方法中完成。无论如何,问题:

如果您希望某些行为在满足或不满足某些条件时以固定方式发生变化,请尝试切换到优先级而不是不等式。在这种情况下,请考虑边距:当总宽度小于 500 时,您希望水平边距为 0,但当总宽度超过 500 时添加 space。您需要的约束条件:

  1. 要求优先级 1000:将 myView 设置为小于或等于 500。
  2. 优先级 999:设置 myView 附加到 superview leading/trailing space=0。

如果space小于500,则两个条件都可以满足。如果 space 大于 500,那么它将开始打破约束,从最低优先级开始。

请注意,在打破边距约束后,它将不知道在哪里设置 myView 的水平 x 位置,因此您将需要另一个约束。在 superview 中居中将冲突最少,因为它可以水平放置它,有或没有边距约束被打破。有一种方法可以让它只在一侧添加 space ,但这是一种复杂的打破约束的舞蹈,导致需要进行混乱的程序干预;我认为水平居中得到你想要的行为。

您需要不止一种约束和使用优先级。 myView 的一个约束等于您已经拥有的超级视图宽度,另一个约束 myView 的 NSLessThanOrEqual 等于 500,如上面所建议的。然后设置后者的优先级大于等宽约束。我认为宽度应该足够了。也许你需要一个优先级较低的第三个约束来将 myView 的宽度设置为 500,如果它仍然缩小到 0 以避免歧义。

这是对我的答案的编辑,其中包含一些代码以更好地说明:

使用如下所示的视觉布局可以使布局更具可读性(一旦您习惯了语法)

 NSDictionary *views = @{@"myView" : _myView, @"superView": self.view};

  [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[myView(40)]" options:0
                                                                    metrics:nil
                                                                      views:views]];

  [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(3@999,>=3)-[myView(<=500)]-(3@999,>=3)-|" options:0
                             metrics:nil
                             views:views]];

如果填充 3 只是为了说明收缩到边缘。

如果您想将 myView 置于父视图视觉布局的中心,您将需要像这样添加一个长格式约束:

  [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.myView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];

但是所有这些都可以在情节提要中完成,而无需任何基于相同逻辑的代码。如果不使用情节提要,我会尝试尽可能多地使用可视化布局,通常只使用长格式来居中视图,或者在结构仅在运行时才知道的动态布局视图时使用。

根据您的问题,您需要为 myView 设置约束。
您需要执行以下操作:

UIView *myView = [UIView new];
myView.translatesAutoresizingMaskIntoConstraints = NO;
myView.backgroundColor = [UIColor blueColor];
[self.view addSubview:myView];

NSDictionary *viewDictionary = @{@"myView":myView};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[myView(200)]" options:0 metrics:0 views:viewDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[myView(<=500)]" options:0 metrics:0 views:viewDictionary]];

NSLayoutConstraint *tailing = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:myView attribute:NSLayoutAttributeTrailingMargin multiplier:1 constant:75];
tailing.priority = 999;
[self.view addConstraint:tailing];

结果:


希望这对解决您的问题有所帮助。
您可以访问此 link 以编程方式设置自动布局约束以获得高级帮助。
参考:http://technet.weblineindia.com/mobile/ui-design-of-ios-apps-with-autolayout-using-constraints-programmatically/

参考:https://codehappily.wordpress.com/2013/10/09/ios-how-to-programmatically-add-auto-layout-constraints-for-a-view-that-will-fit-its-superview/