如何在不使布局模糊的情况下使用大于或等于编程iOS AutoLayout约束?

时间:2014-01-03 15:05:55

标签: c# ios mono xamarin.ios autolayout

我正在使用MonoTouch编写iOS应用程序,我想以编程方式定义我的所有UIViews以及定义其布局的AutoLayout约束。我目前正在尝试创建一个类似于Table的视图集合(行和列,而不是UITableView),并且我能够使用AutoLayout约束来调整列和行“边框”或标记。当我运行应用程序时它看起来很好,但我不断得到一个模糊的表格布局(使用HasAmbiguousLayout字段)。我把它简化为我的边框标记使用GreaterThanOrEqual(GTE)约束而不是Equal的事实,这是必需的,因为我想确保我的行和列适合任意数量的视图。

我的理解是,我可以使用GTE类型约束,而AutoLayout系统将尝试最小化该值,使​​其仍然是GTE(反之亦然,用于LTE约束)。例如,我希望我可以将视图的左侧egde GTE放置在另外两个视图的右边缘,这样布局求解器将确定左边缘的最小值,使得它仍然满足GTE的另一个右边缘视图。

我创建了一个简单的示例,但我不确定为什么会出现模糊的布局。我在MonoTouch中创建了一个单视图项目,并以编程方式添加了一个UIView框作为我的容器(在更复杂的示例中包含多行和多列视图)。然后我只在框视图中添加一个子视图,一个名为myLabel的UILabel。我添加约束以将标签放在框中,将框放在父视图中,并设置框的右边和底边(这是关键部分):

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限制的原因。

AutoLayout test

我的问题是:为什么我不能在这里使用GTE约束来获取我的盒子视图而不会出现模糊的布局?如果这个简单的例子不起作用,你怎么会使用GTE约束(它们都是模棱两可的,否则你会首先将它们指定为Equal)?

感谢您的帮助,

凸轮

1 个答案:

答案 0 :(得分:1)

通常我会做同样的事情,使用GTE来确保某个方面的某些内容有限,但是然后添加另一个具有较低优先级的约束来尝试执行其他操作,例如将视图置于另一个视图中。你必须要有创意。我发现的最好的方法是使用铅笔和纸,画出一个例子,并尝试构建我需要什么约束的地方。

我不相信系统可以平等地分配不等式 - 如果左边有一个,右边有一个,它该怎么办?我使用不等式来确保永远不会超过某个最大值,然后使用不等式来尝试实现某个目标(即居中)。