iOS Autolayout:标签文本变长时如何移动视图

时间:2014-06-10 17:27:09

标签: ios uitableview autolayout

我有一个带有两个标签和一个小图像的tableview单元格。 如果labeltexts很短,那么所有这些都适合这一行:

.________________________________________.
|                                        |
|  [firstlabel] [img] [secondlabel]    > |
|________________________________________|

但是,如果labeltexts变得越来越长,那么图像 第二个标签应移至第二行:

.________________________________________.
|                                        |
|  [firstveryverylonglabel]            > |
|   [img] [secondverylonglabel]          |
|________________________________________|

我如何使用自动布局执行此操作?

第一个标签很简单 - 只需为左侧和顶部添加约束。标签总是只有一行高,如果文本太长,则会在中间被截断。

图像必须始终水平位于第二个标签(默认空间)的前面,并且两者都垂直居中。图像大小应该与标签的动态文本字体大小(preferredFontForTextStyle:UIFontTextStyleBody)一起缩放,这样,如果用户选择大文本,图像也会被绘制得更大。

如果需要两条线,细胞高度当然应该增长。

如果在Interface Builder中设置必要的约束,则可以使用Bonus Points,但如果没有,那么我可以在tableview单元的init例程中使用代码设置它们。

我的应用应该在iOS 7及更高版本下运行 - 不需要iOS 6.所以我必须在tableview中计算高度:heightForCellAtIndexPath:,并且将使用隐藏的单元格让Autolayout在那里发挥其魔力。

2 个答案:

答案 0 :(得分:2)

我最后在代码中设置了约束。我将标签和图像嵌入到另一个视图中,然后为单元格和视图实现了-updateConstraints

-tableView:heightForRowAtIndexPath:中,我首先让Autolayout首先通过静态隐藏单元格(仅用于测量)通过调用layoutIfNeeded来设置contentView,然后强制它通过以下方式更新约束:调用setNeedsUpdateConstraints后跟updateConstraintsIfNeeded,最后使用systemLayoutSizeFittingSize:UILayoutFittingCompressedSize来衡量单元格的高度。

在我看来的updateConstraints方法中,我首先尝试将这些单元格并排排列

  [self removeConstraints];
  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
        @"V:|-margin-[first]-margin-|"
    options:0 metrics:metrics views:views]];
  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
        @"H:|-margin-[first]-[image]-[second]-margin-|"
    options:NSLayoutFormatAlignAllCenterY metrics:metrics views:views]];

然后我在视图上调用systemLayoutSizeFittingSize:UILayoutFittingCompressedSize并将宽度与contentView内的最大可能空间进行比较,给定其固定的水平起始位置。如果它太宽,我需要设置一个两行约束集:

  [self removeConstraints];
  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
        @"V:|-margin-[first]-[second]-margin-|"
    options:0 metrics:metrics views:views]];
  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
        @"H:|-margin-[first]-margin-|"
    options:0 metrics:metrics views:views]];
  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:
        @"H:|-margin-[image]-[second]-margin-|"
    options:NSLayoutFormatAlignAllCenterY metrics:metrics views:views]];

在单元格的updateConstraints方法中,我只是在视图上调用setNeedsUpdateConstraints,以确保在单元格的大小更改后重新计算视图(例如,在旋转肖像时<< ; =>横向)。 就是这样。

答案 1 :(得分:0)

对于带文字的细胞的动态尺寸,我建议您使用UITextView代替UILabel

这是一个函数,它会根据输入的文本和字体来预测UITextView的大小。

-(CGSize)frameForText:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{

    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          font, NSFontAttributeName,
                                          nil];
    CGRect frame = [text boundingRectWithSize:size
                                      options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                   attributes:attributesDictionary
                                      context:nil];

    // This contains both height and width, but we really care about height.
    return frame.size;
}

现在您需要实现的是根据此函数返回单元格的高度:

// This is the method that determines the height of each cell.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {


    // I am using a helper method here to get the text at a given cell.
    NSString *text = [self getTextAtIndex:indexPath];

    // Getting the height needed by the dynamic text view.
    CGSize size = [self frameForText:text sizeWithFont:nil constrainedToSize:CGSizeMake(yourTextView.height, CGFLOAT_MAX)];

    //If the height of textView is larger than your default textView height, 
    //then you need to to give it your default height of your cell + extra 
    //size for your text
    if (size.height>=defaultsize)
    {
        return size.height + defaultCellHeight;
    }
    else
    {
        return defaultCellHeight;
    }

}

我在社交网络应用上使用这些功能,以显示不同小区高度的不同评论! 希望它有所帮助