0

我正在尝试在代码中设置约束并且没有得到预期的结果。

我有一个带有 3 个按钮(子视图)的 UIView 容器,我试图将一个前导空间设置为其他两个前导空间的平均值(所以它会在中间,水平)。当我将 3 个按钮放在我想要的位置时,与我在情节提要上看到的数字相比,我得到的数字似乎是正确的。我通过它们的帧的 x 值获得了前导空间(我已经仔细检查了 alignmentRectForFrame: 给出了相同的结果),并且我对它们进行了平均。

我用:

NSLayoutConstraint *twitterConstraint = [NSLayoutConstraint constraintWithItem:middleButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:average];
[twitterConstraint setPriority:UILayoutPriorityRequired];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
[NSLayoutConstraint activateConstraints:@[twitterConstraint]];

基本功能有效,即如果我输入一个数字而不是平均值,我会看到结果。我用当前的代码得到了意想不到的结果。具体来说,我在其他 2 个按钮的右侧获得了“中间按钮”。

帮助!

伊丹

4

1 回答 1

0

扩展@Ken Thomases 在评论中回答的原因:自动布局首先从子视图向上收集信息,然后从超级视图向下设置框架。因此,此代码对其子视图帧的值进行采样,但在执行时(在updateConstraintsupdateViewConstraints其他地方),这些视图的帧尚未设置为其自动布局批准的值。可能会发生不可预测的结果。

在此视图上调用 -layoutIfNeeded 会强制自动布局引擎为子视图执行此操作——实际上是执行布局工作。因此,对这些子视图进行采样就可以了。

不幸的是,在这种方法中,对帧进行采样以获取信息和调用 layoutIfNeeded 都会产生问题,这会重复昂贵的布局操作。如前所述,它要求按钮的大小都相同。无论如何,对于这个用例来说可能没问题。


使用本机自动布局系统(并允许不同大小的项目)将项目设置为均匀间隔的方法是间隔视图。这是不雅的,但必要的。它可以在 IB 中手动完成,以下是使用 Visual Format Language 的方法:

NSMutableDictionary *autoLayoutDict = [[NSMutableDictionary alloc] init];
NSDictionary *setDictionary = @{
                                @"leftLabel":self.leftLabel,
                                @"middleLabel":self.middleLabel,
                                @"rightLabel":self.rightLabel
                                };
[autoLayoutDict setValuesForKeysWithDictionary:setDictionary];

int numberOfSpacerViewsRequired = 2;
for (int i = 0; i < numberOfSpacerViewsRequired; i++) {

    UIView *spacerViewX = [[UIView alloc] init];
    spacerViewX.backgroundColor = [UIColor clearColor];
    spacerViewX.userInteractionEnabled = NO;
    spacerViewX.translatesAutoresizingMaskIntoConstraints = NO;

    NSString *spacerViewKey = [NSString stringWithFormat:@"spacerView%i", i];
    [autoLayoutDict setObject:spacerViewX forKey:spacerViewKey];

    [self.view addSubview:spacerViewX];
}

NSArray *constraintsToAdd = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[leftLabel]-0-[spacerView0(spacerView1)]-0-[middleLabel]-0-[spacerView1(spacerView0)]-0-[rightLabel]"
                                        options:NSLayoutFormatAlignAllCenterY
                                        metrics:0
                                          views:autoLayoutDict];

[self.view addConstraints:constraintsToAdd];
于 2015-02-16T19:31:30.623 回答