8

我一定在这里遗漏了一些非常明显的东西,但这是一个让我沮丧了好几天的问题。

在 xcode 4.5 上的 iOS 项目中,我在一个 XIB 中有几个标签,一个在另一个之上,在一个UIScrollView占据UIView. 每个标签都与视图一样宽,每个标签都比下一个高 20 px。有时,其中一个标签没有任何信息,因此它被设置为不可见,并且它下面的标签应该向上移动以占据空白空间。

问题是,如果在视图上选中“关闭”自动布局,标签会完全按照它们应该的方式向上移动,尽管UIScrollView不再滚动。如果它是on,无论如何标签都不会移动。

这是代码......我基本上只是使用一个快速功能将每个标签向上移动不可见标签的高度。

[self moveObjectBy: self.festNameLabel moveByY:-(yearsLabel.frame.size.height-2)];


// this just quickly moves a label. 
- (void)moveObjectBy:(UIView *)lbl moveByY:(int)byHeight {
    CGRect newFrame = lbl.frame;
    NSLog(@"%f, %d", newFrame.origin.y, byHeight);
    newFrame.origin.y += byHeight; //yearsLabel.frame.size.height;
    lbl.frame = newFrame;
}

当它运行时,NSLog显示它的 Y 已经移动,但它不会在屏幕上移动。我确定它与垂直空间约束有关,但它不会让我删除约束,也不会让我将其更改为视图顶部空间以外的任何内容。就像我说的,我确定我错过了一些东西,但我已经用尽了我所知道的一切......

4

3 回答 3

14

如果您只有一个可能被隐藏的标签,您可以将其下方的标签移至以下位置:

 -(void)contract {
    self.label2.hidden = YES;
    self.con2To1.constant = -34;
}

顶部标签对滚动视图的顶部有一个约束,所有其他标签对它们上方和下方的标签都有 20 点的垂直距离约束。在这个例子中,我隐藏了 label2。标签都是 34 点高,因此将约束常数从 20 更改为 -34 会将现在隐藏的标签移动到其上方的标签的正上方。

要将此方法与可以隐藏的多个标签一起使用,您需要为要隐藏的每个标签及其对上面标签的约束设置一个出口。实际上,您可以在没有约束条件的情况下做到这一点,但我不知道它是否会那么健壮(它可能会选择错误的约束条件)。我可以通过遍历约束来找到与特定标签一起使用的约束,并且是该标签顶部的约束,从而可以做同样的事情:

-(void)hideLabel:(UILabel *) label {
    label.hidden = YES;
    for (NSLayoutConstraint *con in self.scroller.constraints) {
        if (con.firstItem == label  && con.firstAttribute == NSLayoutAttributeTop) {
            con.constant = -34;
        }
    }
}

如果您愿意,可以修改相同的方法以使用动画——以下代码片段淡出您要隐藏的标签,同时为所有较低标签的上移设置动画。

 -(void)hideLabel:(UILabel *) label {
    for (NSLayoutConstraint *con in self.scroller.constraints) {
        if (con.firstItem == label  && con.firstAttribute == NSLayoutAttributeTop) {
            con.constant = -34;
            [UIView animateWithDuration:.5 animations:^{
                label.alpha = 0;
                [self.scroller layoutIfNeeded];
            }];
        }
    }
}
于 2012-12-24T23:53:57.907 回答
5

使用自动布局,您不能在子视图上设置框架 - 充其量,它会暂时工作,直到发生下一个布局传递。此时,您的约束定义的布局将重新建立。

您需要做的是修改视图上的约束。在您的情况下,在每个标签上设置特定的引脚到高度约束是明智的。然后,您可以为这些约束中的每一个创建出口。对于零高度标签,您需要将相关约束上的常量设置为零。然后下面的标签将向上移动。

根据您要移除的标签,这可能会给您留下两倍宽的间隙。您可以通过修改间距约束来删除它,或者您可以完全摆脱间距约束,只是让每个标签高一点,但彼此相邻 - 标签的内容无论如何都会垂直居中。

主要信息是您没有设置框架。您改为修改、添加和/或删除约束。

于 2012-12-24T21:02:15.780 回答
0

如果您想快速执行此操作:

for item in self.view.constraints
{
    if item.firstItem .isKindOfClass(UITextField)
    {
        let newField = item.firstItem as! UITextField
        if newField == answerTextField && item.firstAttribute == NSLayoutAttribute.Top
        {
            item.constant = answerFrame.origin.y
            self.view .layoutIfNeeded()
        }
    }
    if item.firstItem .isKindOfClass(UIButton)
    {
        let newField = item.firstItem as! UIButton
        if newField == submitButton && item.firstAttribute == NSLayoutAttribute.Top
        {
            item.constant = submitFrame.origin.y
            self.view .layoutIfNeeded()
        }
    }
}
于 2016-04-28T10:53:02.833 回答