无法在视图中使用Autolayout“on”移动UILabel的Y位置

时间:2012-12-24 20:14:23

标签: iphone objective-c ios autolayout

我必须在这里遗漏一些非常明显的东西,但这是一个让DAYS感到沮丧的问题。

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

问题是,如果在视图上选中“关闭”自动布局,标签会尽可能地向上移动,尽管UIScrollView不再滚动。如果 ,标签根本不会移动,无论如何。

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

[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已移动,但它不会在屏幕上移动。我确定它与垂直空间约束有关,但它不会让我删除约束,它不会让我从视图顶部将其更改为空间以外的任何内容。就像我说的,我确定我错过了什么,但我已经筋疲力尽了我所知道的一切......

3 个答案:

答案 0 :(得分: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];
            }];
        }
    }
}

答案 1 :(得分:5)

使用自动布局后,您无法在子视图上设置框架 - 充其量,它将暂时有效,直到发生下一个布局过程。此时,将重新建立由约束定义的布局。

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

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

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

答案 2 :(得分:0)

如果你想在swift中这样做:

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()
        }
    }
}