如何使用大于或等于编程 iOS AutoLayout 约束而不使布局模糊?
Posted
技术标签:
【中文标题】如何使用大于或等于编程 iOS AutoLayout 约束而不使布局模糊?【英文标题】:How can I program iOS AutoLayout constraints using Greater Than or Equal without making the layout ambiguous? 【发布时间】:2014-01-03 15:05:55 【问题描述】:我正在使用 MonoTouch 编写一个 ios 应用程序,我想以编程方式定义我的所有 UIView 和定义其布局的 AutoLayout 约束。我目前正在尝试创建一个类似于表格的视图集合(行和列,而不是 UITableView),并且我能够使用 AutoLayout 约束来调整列和行的“边框”或标记。当我运行应用程序时它看起来很好,但我不断得到一个不明确的表格布局(使用 HasAmbiguousLayout 字段)。我将其提炼为我的边界标记使用 GreaterThanOrEqual (GTE) 约束而不是 Equal,这是必需的,因为我想确保我的行和列适合任意数量的视图。
我的理解是我可以使用 GTE 类型约束,并且 AutoLayout 系统将尝试最小化该值,使其仍然是 GTE(LTE 约束反之亦然)。例如,我希望我可以将一个视图的左 egde GTE 放置在其他 2 个视图的右边缘,以便布局求解器确定左边缘的最小值,这样它仍然满足另一个右边缘的 GTE意见。
我创建了一个简单的示例,但我不确定为什么会得到一个模棱两可的布局。我在 MonoTouch 中创建了一个单视图项目,并以编程方式添加了一个 UIView 框作为我的容器(在更复杂的示例中,它包含多行和多列视图)。然后我只将 1 个子视图添加到框视图中,一个名为 myLabel 的 UILabel。我添加约束将标签放置在盒子内,将盒子放置在父View内,并设置盒子的右下边缘(这是关键部分):
public partial class AutoLayoutTestViewController : UIViewController
public AutoLayoutTestViewController () : base ("AutoLayoutTestViewController", null)
UIView box = new UIView ();
box.BackgroundColor = UIColor.Green;
box.TranslatesAutoresizingMaskIntoConstraints = false;
View.AddSubview (box);
View.AddConstraint (NSLayoutConstraint.Create (box, NSLayoutAttribute.Top, NSLayoutRelation.Equal, View, NSLayoutAttribute.Top, 1.0f, 50f));
View.AddConstraint (NSLayoutConstraint.Create (box, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1.0f, 0f));
UILabel myLabel = new UILabel ();
myLabel.Text = "My Label";
myLabel.BackgroundColor = UIColor.Red;
myLabel.TranslatesAutoresizingMaskIntoConstraints = false;
box.AddSubview (myLabel);
box.AddConstraint (NSLayoutConstraint.Create (myLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, box, NSLayoutAttribute.Top, 1.0f, 10f));
box.AddConstraint (NSLayoutConstraint.Create (myLabel, NSLayoutAttribute.Left, NSLayoutRelation.Equal, box, NSLayoutAttribute.Left, 1.0f, 10f));
// IMPORTANT CONSTRAINTS
box.AddConstraint (NSLayoutConstraint.Create (box, NSLayoutAttribute.Bottom, NSLayoutRelation.GreaterThanOrEqual, myLabel, NSLayoutAttribute.Bottom, 1.0f, 10f));
box.AddConstraint (NSLayoutConstraint.Create (box, NSLayoutAttribute.Right, NSLayoutRelation.GreaterThanOrEqual, myLabel, NSLayoutAttribute.Right, 1.0f, 10f));
public override void DidReceiveMemoryWarning ()
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
public override void ViewDidLayoutSubviews ()
base.ViewDidLayoutSubviews ();
foreach (UIView v in View.Subviews)
if (v.HasAmbiguousLayout)
Console.WriteLine ("WARNING: View 0 has ambiguous layout!", v);
public override void ViewDidLoad ()
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
以下屏幕截图显示框和标签显示为我想要的,但是当视图控制器完成子视图的布局时,我收到我的框布局不明确的消息。如果我将框的右边缘和下边缘的“重要约束”更改为等于而不是 GreaterThanOrEqual,则布局不再模棱两可。同样,重要的是我能够将我的约束指定为 GTE,因为我正在设置与行和列中任意数量的视图相关的边框,因此当我向表中添加新视图时,我确保我的权利边缘被限制为所有视图的 GTE,并且对于底部边缘也是如此。我不能在我的应用程序中使用严格等于,因为我不知道表格中的哪个子视图将是最右边或最底部的视图;这就是有 GTE 约束的原因。
我的问题是:为什么我不能在这里为我的框视图使用 GTE 约束而不会得到不明确的布局?如果这个简单的例子不起作用,那么你将如何使用 GTE 约束(它们都是模棱两可的,否则你会首先将它们指定为 Equal)?
感谢您的帮助,
摄像头
【问题讨论】:
通常我做同样的事情,使用 GTE 来确保某些东西在一个维度上受到限制,然后添加另一个优先级较低的约束来尝试做其他事情,比如将视图居中于另一个看法。你必须要有创意。我发现最好的方法是使用铅笔和纸,画出一个例子,然后尝试在我需要什么约束的地方构建。祝你好运! 不清楚为什么需要 GTE 约束。当您添加新框时,您是否希望现有框更靠近?您在谈论“我正在针对任意数量的视图设置我的边界”的边界是什么?另外,您是否有理由不使用 UICollectionView 来执行此操作? @rdelmar,这样想吧,我正在构建一个简单的表格,其中包含不同大小和形状的各种视图,但每列的左右边缘应与顶部和底部边缘对齐的每一行。因此,在不知道每一列包含什么的情况下,我希望下一列从 GTE 前一列中的每个 UIView 开始。它只是对齐一切。我的示例只是说明我的 AutoLayout 约束问题,不要介意我只向盒子容器添加 1 个视图(它是一个 1x1 表)。这说明清楚了吗? @rdelmar,我发现 UICollectionView 更适合相同大小视图的网格布局,而且它似乎需要比我最终实现的更多的设置,除了事实上,它被认为是模棱两可的。我的问题真正归结为如何正确使用 GTE 约束,同时使布局明确。如果我在视图的边缘上应用多个 GTE 约束,它确实可以工作,并且它将边缘设置为 smallest 值 st 它仍然满足所有 GTE 约束。这就是我在这里想要做的,但想知道为什么它说它是模棱两可的。 @DavidH,你说得对,我添加了较低优先级的约束来尝试将两个边缘推到最低限度(右边缘 == 左边缘和下边缘 == 优先级为 500 的顶部边缘)。我想知道在使用不等式约束时这是否总是必要的?这似乎有点多余,因为系统已经解决了找到最小值 GTE(或最大值 LTE)的约束。不过,从现在开始,我将使用这种方法,以避免出现歧义警告。谢谢! 【参考方案1】:通常我做同样的事情,使用 GTE 来确保某些东西在一个维度上受到限制,然后添加另一个优先级较低的约束来尝试做其他事情,比如在另一个视图中居中视图。你必须要有创意。我发现最好的方法是使用铅笔和纸,勾勒出一个例子,然后尝试在我需要什么约束的地方构建。
我不相信系统可以平等地分配不等式 - 如果你有一个在左边,一个在右边,它应该怎么做?我使用不等式来确保永远不会超过某个最大值,然后使用较低优先级的来尝试实现某个目标(即居中)。
【讨论】:
以上是关于如何使用大于或等于编程 iOS AutoLayout 约束而不使布局模糊?的主要内容,如果未能解决你的问题,请参考以下文章
如何找到小于或等于 X 的最大值和大于或等于 X 的最小值?