以编程方式创建布局约束

pie*_*e23 84 constraints objective-c ios autolayout

我知道很多人已经就此问了很多问题,但即使有了答案,我也无法让它发挥作用.

当我在故事板上处理约束时,它很容易,但在代码中我很难.例如,我尝试使视图保持在右侧,并根据屏幕方向具有屏幕高度.这是我的代码:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];
Run Code Online (Sandbox Code Playgroud)

它不满足某些约束.我没有看到什么是错的.另外,为什么我不能像使用像self.myView本地变量这样的属性myView

lar*_*cus 106

在代码中使用自动布局时,设置框架不执行任何操作.因此,在上面的视图中指定宽度为200的事实,在您对其设置约束时没有任何意义.为了使视图的约束集明确无误,它需要四个方面:x位置,y位置,宽度和任何给定状态的高度.

目前在上面的代码中,您只有两个(相对于superview的高度,相对于superview的y位置).除此之外,还有两个必需的约束可能会发生冲突,具体取决于视图的超视图约束的设置方式.如果 superview具有一个必需的约束,指定它的高度值小于748,那么你将得到一个"不可满足的约束"异常.

在设置约束之前设置视图宽度这一事实并不意味着什么.它甚至不会考虑旧框架,并将根据它为这些视图指定的所有约束来计算新框架.在处理代码中的autolayout时,我通常只是使用initWithFrame:CGRectZero或简单地创建一个新视图init.

要创建您在问题中口头描述的布局所需的约束集,您需要添加一些水平约束来绑定宽度和x位置,以便提供完全指定的布局:

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:[myView(==200)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];
Run Code Online (Sandbox Code Playgroud)

口头描述此布局从垂直约束开始如下所示:

myView将填充其superview的高度,顶部和底部填充等于标准空间.myView的superview最小高度为748pts.myView的宽度为200pts,并且在其superview上有一个等于标准空间的右边距.

如果您只是希望视图在不限制超视图高度的情况下填充整个超视图的高度,那么您只需省略(>=748)可视格式文本中的参数.如果您认为该(>=748)参数需要给它一个高度 - 在这种情况下你不会:使用bar(|)或带有空格(|-,-|)语法的条形图将视图固定到superview的边缘,你给你的视图一个y -position(固定单边上的视图)和带高度的y位置(固定两边的视图),从而满足视图的约束集.

关于你的第二个问题:

使用NSDictionaryOfVariableBindings(self.myView)(如果你有myView的属性设置)并将其输入你的VFL以用于self.myView你的VFL文本,当autolayout尝试解析你的VFL文本时,你可能会遇到异常.它与字典键中的点表示法和试图使用的系统有关valueForKeyPath:. 在这里查看类似的问题和答案.


Bri*_*OnH 61

嗨,我一直在使用这个页面很多限制和"如何".我花了很长时间才意识到我需要:

myView.translatesAutoresizingMaskIntoConstraints = NO;
Run Code Online (Sandbox Code Playgroud)

让这个例子起作用.感谢Userxxx,Rob M.,特别是larsacus的解释和代码,它非常宝贵.

以下是完整的代码,以便运行上面的示例:

UIView *myView = [[UIView alloc] init];
myView.backgroundColor = [UIColor redColor];
myView.translatesAutoresizingMaskIntoConstraints = NO;  //This part hung me up 
[self.view addSubview:myView];
//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:[myView(==200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];
Run Code Online (Sandbox Code Playgroud)


Sur*_*gch 10

Swift版本

针对Swift 3进行了更新

此示例将显示两种方法,以编程方式添加以下约束,就像在Interface Builder中一样:

宽度和高度

在此输入图像描述

集装箱中心

在此输入图像描述

Boilerplate代码

override func viewDidLoad() {
    super.viewDidLoad()

    // set up the view
    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add constraints code here (choose one of the methods below)
    // ...
}
Run Code Online (Sandbox Code Playgroud)

方法1:锚式

// width and height
myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

// center in container
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Run Code Online (Sandbox Code Playgroud)

方法2:NSLayoutConstraint样式

// width and height
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true

// center in container
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
Run Code Online (Sandbox Code Playgroud)

笔记

  • Anchor样式是NSLayoutConstraintStyle 的首选方法,但它仅适用于iOS 9,所以如果你支持iOS 8,那么你仍然应该使用NSLayoutConstraintStyle.
  • 另请参见"以编程方式创建约束"文档.
  • 有关添加固定约束的类似示例,请参阅此答案.


iDe*_*Dev 5

关于您关于属性的第二个问题,self.myView只有在课堂上将其声明为属性时才能使用.由于myView是局部变量,因此不能以这种方式使用它.有关这方面的更多详细信息,我建议您浏览声明属性上的Apple文档,


Meg*_*ing 5

为什么我不能使用self.myView像myView 这样的局部变量这样的属性?

尝试使用:

NSDictionaryOfVariableBindings(_view)
Run Code Online (Sandbox Code Playgroud)

代替 self.view