为什么NSLayoutAttributeCenterX与NSLayoutAttributeWidth的“无效配对”

时间:2012-12-13 20:15:06

标签: ios6 autolayout nslayoutconstraint

我正在尝试让自动布局管理器根据超级视图的宽度调整视图的中心点。我不明白为什么这是属性的“无效配对”(由崩溃和NSInvalidArgumentException告知)

UIView *ac;
NSLayoutConstraint *cXloc = [NSLayoutConstraint constraintWithItem:ac 
                                                         attribute:NSLayoutAttributeCenterX 
                                                         relatedBy:NSLayoutRelationEqual 
                                                            toItem:ac.superview 
                                                         attribute:NSLayoutAttributeWidth 
                                                        multiplier:.1 
                                                          constant:x*ac.superview.frame.size.width*.2];
[ac.superview addConstraint:cXloc];

有人可以解释为什么这是一个'无效的配对'以及我应该如何处理这个问题? 感谢

4 个答案:

答案 0 :(得分:4)

这是Auto Layout当前实施的限制。但是,您可以轻松解决它,因为所有约束都是线性的,并且NSLayoutAttribute是相关的。例如,您想要的约束是:

subview.centerX = m * superview.width + c;

您可以将其表达为牵引centerX s:

之间的关系
// Since width == 2 * centerX
subview.centerX = m * 2 * superview.centerX + c;

答案 1 :(得分:3)

如果将ac的AttributeCenterX与其superview的AttributeCenterX,AttributeLeading或AttributeTrailing相关联,则应该能够使用乘数和约束来表达所需的约束。请记住,只有在创建约束时才会计算常量,并且当ac.superview的宽度发生变化时,示例的常量不会更新。

如果您可以用文字表达您对其超级视图的定位方式,我们可以建议约束。

修改

以下是5个NSButton的示例。它们本身和它们之间的空间扩大,使得空间比按钮宽30%,所有按钮具有相同的宽度,并且所有空间具有相同的宽度。仅为间距创建4个不可见的NSView非常麻烦,特别是考虑到你已经在autolayout之外工作了。但万一你好奇:

// Assuming these NSViews and NSButtons exist,
//NSView* superview ;
//NSButton *buttonOne, *buttonTwo, *buttonThree, *buttonFour, *buttonFive ;


[superView removeConstraints:superView.constraints] ;

// Create empty NSViews to fill the space between the 5 buttons.
NSView* spaceOne = [NSView new] ;
NSView* spaceTwo = [NSView new] ;
NSView* spaceThree = [NSView new] ;
NSView* spaceFour = [NSView new] ;
spaceOne.translatesAutoresizingMaskIntoConstraints = NO ;
spaceTwo.translatesAutoresizingMaskIntoConstraints = NO ;
spaceThree.translatesAutoresizingMaskIntoConstraints = NO ;
spaceFour.translatesAutoresizingMaskIntoConstraints = NO ;
[superView addSubview:spaceOne] ;
[superView addSubview:spaceTwo] ;
[superView addSubview:spaceThree] ;
[superView addSubview:spaceFour] ;

NSDictionary* views = NSDictionaryOfVariableBindings(superView,buttonOne,buttonTwo,buttonThree,buttonFour,buttonFive,spaceOne,spaceTwo,spaceThree,spaceFour) ;

// Vertically align buttonOne to its superview however you like.
[superView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonOne]"  options:0  metrics:nil  views:views ] ] ;

// Make the "space" NSViews' widths equal and >= 10. Make the buttons' widths equal.
[superView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[buttonOne][spaceOne(>=10)][buttonTwo(==buttonOne)][spaceTwo(==spaceOne)][buttonThree(==buttonOne)][spaceThree(==spaceOne)][buttonFour(==buttonOne)][spaceFour(==spaceOne)][buttonFive(==buttonOne)]|"  options: NSLayoutFormatAlignAllCenterY  metrics:nil  views:views ] ] ;
// Make the "space" NSViews' widths 30% of the NSButtons' widths.
[superView addConstraint: [NSLayoutConstraint constraintWithItem: spaceOne
                                                       attribute: NSLayoutAttributeWidth
                                                       relatedBy: NSLayoutRelationEqual
                                                          toItem: buttonOne
                                                       attribute: NSLayoutAttributeWidth
                                                      multiplier: 0.3
                                                        constant: 0 ] ] ;

答案 2 :(得分:1)

基于an0的答案,并假设您有一个包含按钮的NSArray,以下内容应该在超级视图中平均分隔按钮:

  NSUInteger currentButton = 1;
  for (UIButton *button in self.buttons)
  {
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:2.0 * (CGFloat) currentButton / (CGFloat) (self.buttons.count + 1) constant:0.0]];
    currentButton++;
  }

答案 3 :(得分:0)

如果您希望以编程方式生成的视图符合其超视图的宽度。您可以使用NSLayoutAttributeLeadingattribute:NSLayoutAttributeCenterX

的约束配对

您必须进行正确的计算才能获得正确的乘数。计算涉及要布置的视图的总数和当前视图的索引。

    //Caculate constraint multiplier from parentView CenterX.
    //This sets the width of the button relative to parentView.
    // A value of 2 = Full width.

    CGFloat multiplier = 2/(arr.count/counter);

    [parentView addConstraint:[NSLayoutConstraint constraintWithItem:btn
                    attribute:NSLayoutAttributeTrailing
                    relatedBy:NSLayoutRelationEqual toItem:parentView
                    attribute:NSLayoutAttributeCenterX multiplier:multiplier constant:0]];

这将分配视图宽度以填充其超级视图。