如何使用大于或等于编程 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 约束而不使布局模糊?的主要内容,如果未能解决你的问题,请参考以下文章

如何过滤大于或等于空?

如何在 switch 语句中使用大于或等于

如何找到小于或等于 X 的最大值和大于或等于 X 的最小值?

如何在javascript中使用moment(moment.js)做大于或等于?

如何修复“索引(基于零)必须大于或等于零”错误[重复]

linux命令 SHELL编程:从键盘输入一个数,若大于0,则输出该数;若小于或等于0,则输出0值。程序怎么写