处理动态UITableViewCell高度的更好方法是什么?

时间:2012-05-31 21:34:27

标签: iphone cocoa-touch dynamic uitableview

我正在实现一个UITableView,其中表格单元格包含多个控件,例如标签和按钮。朝向单元顶部的标签之一可以具有不同数量的文本,因此每个单元的整个尺寸也必须变化。所以基本上,这是你在整个地方看到的动态表格单元格问题。

我似乎找到的事实上的解决方案是this one 我正在使用它,但我并不关心它,因为它带有维护问题。因为我在单元格中有很多其他东西,所以我必须有很多硬编码的高度来表示在确定单元格的整体大小时以及根据单元格的大小放置所有内容时必须考虑的所有其他控件。动态内容。

以下是一些代码:

- (CGFloat) tableView:(UITableView*)tableView
            heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
    SomeDataItem* item = [self.myData objectAtIndex:indexPath.row];
    CGSize constraintSize = CGSizeMake(275, MAXFLOAT);
    CGSize labelSize = [item.message sizeWithFont:[UIFont systemFontOfSize:13]
                                constrainedToSize:constraintSize 
                                    lineBreakMode:UILineBreakModeWordWrap];

    return HEADER_HEIGHT + OUTER_MARGIN + labelSize.height +
           INNER_MARGIN + INNER_MARGIN + OUTER_MARGIN +
           BUTTON_HEIGHT + OUTER_MARGIN;
}

- (UITableViewCell*)tableView:(UITableView*)tableView
                    cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    ...
    NSString* message = //some dynamic text
    CGSize constraintSize = CGSizeMake(275, MAXFLOAT);
    CGSize labelSize = [message sizeWithFont:[UIFont systemFontOfSize:13]
                           constrainedToSize:constraintSize
                               lineBreakMode:UILineBreakModeWordWrap];

    //resize label according to amount of text
    cell.messageLabel.frame = CGRectMake(cell.messageLabel.frame.origin.x,
                                         cell.messageLabel.frame.origin.y,
                                         cell.messageLabel.frame.size.width, 
                                         labelSize.height);

    //now move controls below the dynamic label down
    y = HEADER_HEIGHT + OUTER_MARGIN;
    [self setView:cell.messageTextBackground yCoord:y];

    y += INNER_MARGIN;
    [self setView:cell.messageLabel yCoord:y];

    y += labelSize.height;
    [self setView:cell.anotherLabel yCoord:y];

    y += OUTER_MARGIN;
    [self setView:cell.someButton yCoord:y];
}

- (void) setView:(UIView*)view yCoord:(NSInteger)y
{
    int x = view.frame.origin.x;
    int w = view.frame.size.width;
    int h = view.frame.size.height;
    view.frame = CGRectMake(x, y, w, h);
}

这只是代码的近似值,可以让您了解我在做什么。你可以看到,这有点乱。如果我必须为动态标签旁边的所有其他控件保留#define值。如果我想更改任何这些控件的大小,我必须在XIB文件中执行此操作,然后还要记住更新#define值。更糟糕的是,如果我想引入一些新的控件,我必须修改这两种方法,并确保所有内容仍然得到正确的计算和偏移。

这对我来说似乎很荒谬,但我还没有找到任何其他方法来做到这一点。如果只能访问tableView:heightForRowAtIndexPath中的表格单元格,那么您可以根据实际控件计算所有内容,而不必对所有内容进行硬编码。但是,从我阅读和体验过的tableView:heightForRowAtIndexPath在单元格存在之前被调用,所以你不能这样做。

关于我如何处理这个问题,或者这是唯一的方法吗?

2 个答案:

答案 0 :(得分:3)

更干净地处理这种情况的一种可能方法是将所有非变化视图/控件放入具有固定大小的父视图中,然后您可以只询问该视图的框架并使用高度。这样,如果您编辑视图的静态部分,则调整大小代码不需要更改。此外,由于您只需移动封闭视图,因此可以更轻松地移动静态项目。

答案 1 :(得分:1)

我认为你做的是正确的事。至少我已经有一段时间做了这件事。维护应该没问题,你只需要做你提到的事情。

您可以通过使用单元格的XIB文件,在#define中加载xib文件并提取其中各种元素的大小来减少viewDidLoad语句。然后,您将来只需要在XIB文件中更改它们。

当然,包含不变元素的包装视图可能是一个额外的帮助。