UITableViewCell的动态高度和里面的内容

时间:2013-09-24 15:15:15

标签: iphone ios objective-c uitableview

我有一个特别的问题,我似乎无法解决我已经看了几个小时的代码,似乎无法解决问题。

当我向我的tableview添加消息时,消息会溢出UITableViewCell中的包装器,有时包装器会被单元格截断。

如何确保我的包装器总是足够大以容纳txt(lblMessage) 并且单元格足以容纳包装器。

提前致谢!

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat height = [self heightForMessage:indexPath];

    if(height < 50)
    {
        NSLog(@"Normal : %d , row : %d", 100,indexPath.row);
        return 100;
    }    
    else
    {
        NSLog(@"Custom : %f , row : %d", 70 + height,indexPath.row);
        return 70 + height;
    }
}

-(CGFloat)heightForMessage:(NSIndexPath *)indexPath
{
    MessageObject * model = [self.chats objectAtIndex:indexPath.row];

    CGSize size = [model.message sizeWithFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:12] constrainedToSize:CGSizeMake(290, 100000) lineBreakMode:NSLineBreakByWordWrapping];

    return size.height;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * NewsCellIdentifer = @"NewsCellIdentifier";
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer];

    UILabel * lblContact;
    UILabel * lblMessage;
    UILabel * lblDate;
    UIView * wrapper;

    if (cell == nil)
    {

        /* Top menu for login */

        wrapper = [[UIView alloc] initWithFrame:CGRectMake(10, 5, 300, 90)];
        [wrapper setBackgroundColor:[self.delegate.color colorWithAlphaComponent:0.6f]];
        [wrapper.layer setCornerRadius:6.0f];
        [wrapper.layer setShadowOffset:CGSizeMake(0, 2)];
        [wrapper.layer setShadowRadius:2.0f];
        [wrapper.layer setShadowOpacity:0.5f];
        [wrapper viewWithTag:19];
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NewsCellIdentifer];

        /* Contact Name */

        lblContact = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 150, 30)];
        [lblContact setFont:[UIFont fontWithName:@"HelveticaNeue-Medium" size:13]];
        [lblContact setTag:13];
        [lblContact setTextColor:[self.delegate colorFromHexString:@"#fffbff"]];
        [lblContact setBackgroundColor:[UIColor clearColor]];

        /* Received Message */

        lblMessage = [[UILabel alloc] initWithFrame:CGRectMake(10, 20, 280, 50)];
        [lblMessage setNumberOfLines:0];
        [lblMessage setLineBreakMode:NSLineBreakByWordWrapping];
        [lblMessage setBackgroundColor:[UIColor clearColor]];
        [lblMessage setFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:12]];
        [lblMessage setTextColor:[self.delegate colorFromHexString:@"#fffbff"]];
        [lblMessage setTag:14];


        /* Date received */

        lblDate = [[UILabel alloc] initWithFrame:CGRectMake(10, 65, 65, 30)];
        [lblDate setText:@"4 hours ago"];
        [lblDate setFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:11]];
        [lblDate setTextColor:[self.delegate colorFromHexString:@"#fffbff"]];
        [lblDate setTag:15];

        /* Subview Logic */

        [wrapper addSubview:lblContact];
        [wrapper addSubview:lblMessage];
        [wrapper addSubview:lblDate];

        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
        [cell.contentView addSubview:wrapper];
    }
    else
    {
        lblContact = (UILabel *)[cell.contentView viewWithTag:13];
        lblMessage = (UILabel *)[cell.contentView viewWithTag:14];
        wrapper = [cell.contentView viewWithTag:19];
    }

    MessageObject * model = [self.chats objectAtIndex:indexPath.row];

    CGFloat height = [self heightForMessage:indexPath];

    [lblMessage setFrame:CGRectMake(10, 25, 280, height)];
    [lblMessage setText:model.message];

    [lblContact setText:model.clientModel.firstName];

    if(height < 50)
    {
        NSLog(@"wrapper size : %d for row %d ", 90, indexPath.row);
        [wrapper setFrame:CGRectMake(10, 5, 300, 90)];
    }
    else
    {
        NSLog(@"wrapper size : %f for row %d ", height + 60, indexPath.row);

        [wrapper setFrame:CGRectMake(10, 5, 300, height + 60)];
        [lblDate setFrame:CGRectMake(10, height + 20, 65, 30)];
    }

    [cell.contentView setBackgroundColor:[UIColor greenColor]];
    [cell setBackgroundColor:[UIColor clearColor]];

    return cell;
 }

6 个答案:

答案 0 :(得分:2)

考虑显着改善你的代码......因为现在几乎不可读了 1)摆脱硬编码,例如20,280。而是考虑使用常数(CONTACT_LABEL_TO_MESSAGE_LABEL_OFFSET,MESSAGE_LABEL_WIDTH)
2)摆脱向UITableViewCell添加自定义子视图并使用硬编码(参见1)数字标记它们 - 而不是子类UITableViewCell,在.xib或.storyboard中创建原型,为您的类创建方便的方法 - 例如setDate:,setMessage:,setContactName: 。所有帧都应在子类-layoutSubviews方法中计算。

初看:
1)您将宽度设置为280到lblMessage,当您将文本的宽度限制为290时,会导致错误的高度计算

答案 1 :(得分:1)

我建议使用原型单元并通过使用给定索引路径的数据逐字配置原型来计算单元高度。只需将一个单元格出列(是的,您可以在cellForRowAtIndexPath之外执行此操作)并保留它以进行高度计算。对于动态高度标签,您通常在单元的配置逻辑中调用[label sizeToFit]。在this question中对此技术进行了更详细的讨论。

如果您想查看第三方库,我的TLIndexPathTools库提供了一个基表视图类TLTableViewController,内置支持使用原型的动态行高:

  1. 对于静态,非数据驱动的高度,它将返回原型的默认高度。因此,如果您的原型来自Storyboard,它将遵循Storyboard自定义单元格高度。
  2. 对于动态,数据驱动的高度,任何实现TLDynamicHeightView协议的自定义单元格都将自动计算动态高度。

答案 2 :(得分:1)

其中一个错误是当您为新单元格创建包装视图时:

[wrapper viewWithTag:19];

应该是:

[wrapper setTag:19];

当您尝试在重用的单元格上调整它时,这可能会导致wrapper为nil。

答案 3 :(得分:1)

我会告诉你我用来解决这个问题的方法。

  • 使用array存储高度(使用sizeWithFont)。现在已弃用,因此您应尝试使用sizeWithAttributes
  • 记录array的高度和实际标签的高度,看看它们是否匹配。
  • 确保在UIFont和yourLabel.font使用的sizeWithFont相同。
  • 检查单元格中是否有任何类型的填充,例如在单元格的顶部留下像素。

这些是一般提示。

答案 4 :(得分:0)

tableView: cellForRowAtIndexPath:中创建单元格时,您可以将其存储到NSMutableArray中 然后,tableView: heightForRowAtIndexPath:只需检索单元格并指定高度。

这是我大多数时间都这样做的,但是如果你使用很多的单元格,它可能会用到很多内存。 或者,您可以只在NSMutableArray中存储单元格的大小。


编辑:

我不确定我是否理解正确。
您希望您的单元格能够包含您的包装吗?

cell.contentView.frame = CGRectMake(0,0,cell.contentView.frame.size.width,wrapper.frame.origin.y + wrapper.frame.size.height);

将单元格存储在tableView: cellForRowAtIndexPath:中的NSMutableArray中,根据tableView: heightForRowAtIndexPath:

中的索引检索它

答案 5 :(得分:0)

要计算标签高度,您应该考虑不同的事情,您必须通过记住文本长度及其字体以及要添加的帧的边界来计算大小。下面是如何计算动态文本大小的示例。 / p>

CGSize boundingSize = CGSizeMake(frame.size.width, CGFLOAT_MAX);
    CGSize requiredSize = [text sizeWithFont:yourFont constrainedToSize:boundingSize lineBreakMode:NSLineBreakByWordWrapping];