【问题标题】:UITableView has an "ugly" background image for dynamic height rowsUITableView 有一个用于动态高度行的“丑陋”背景图像
【发布时间】:2010-01-18 21:58:45
【问题描述】:

我创建了一个 UITableViewController,它根据包含的文本量计算每行的高度。计算行高的代码如下所示:

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
    Message *message = [[[[SessionData sharedSessionData] sessions] objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
    CGSize size = [[message text] sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

    return size.height + (CELL_CONTENT_MARGIN * 2) + 38;
}

您可能会注意到,我使用一个单独的类作为 UITableViewDatasource,称为 SessionData。在 SessionData 类中,我绘制行。每行都有一个顶部图像、中心图像(根据行高重复)和底部图像。我的问题如下:中心图像比底部和顶部图像更暗。我的猜测是这与图像的重复性质有关,因为顶部和底部的图像绘制得很好。以下代码是我的 [tableView:cellForRowAtIndexPath:] 消息的一部分:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // other stuff here, most likely not related to my issue ...

    Message *message  = [[sessions objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];       
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
    CGSize size = [[message text] sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

    [label setText:[message text]];
    [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN - 5.0f, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), size.height)];
    [label setBackgroundColor:[UIColor clearColor]];

    viewTop = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"im1 top.png"]];
    viewMid = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"im1 mid.png"]];
    viewBot = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"im1 bot.png"]];      

    [viewTop setFrame:CGRectMake(0.0, 0.0, 300.0, 17.0)];
    [viewMid setFrame:CGRectMake(0.0, 17.0, 300.0, size.height - 10)];
    [viewBot setFrame:CGRectMake(0.0, 17.0 + size.height - 10, 300.0, 31.0)];

    [viewTop setBackgroundColor:[UIColor clearColor]];
    [viewMid setBackgroundColor:[UIColor clearColor]];
    [viewBot setBackgroundColor:[UIColor clearColor]];  

    [cell.backgroundView setBackgroundColor:[UIColor clearColor]];

    [((UIImageView *)cell.backgroundView) addSubview:viewTop];  
    [((UIImageView *)cell.backgroundView) addSubview:viewMid];  
    [((UIImageView *)cell.backgroundView) addSubview:viewBot];

    [[cell backgroundView] addSubview:label];   

    return cell;
}

我的猜测是我需要为顶部、中心和底部图像视图创建一个具有总大小(宽度、高度)的 containerView,并将 containerView 添加到单元格中,但这似乎不起作用。有人知道如何解决这个问题吗?

请注意:我的 UITableViewController 有一个渐变作为背景图像。所以顶部/中心/底部图像绘制在背景渐变的顶部。也许这也是问题的一部分。

【问题讨论】:

    标签: uitableview dynamic uiimageview height row


    【解决方案1】:

    这里有几点需要注意。

    首先,您的单元格中正在进行大量处理,这将导致设备上的滚动性能非常差。您应该更好地利用重新排队单元并执行大多数单元设置,这对这里的所有单元都是通用的:

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
            // Do cell layout in here!
        }
    

    这样,单元格及其子视图可以重复使用,而不是每次单元格出现在屏幕上时都重新创建(使用视图的tag 属性和viewWithTag: 方法)。

    其次,你不妨看看stretchable images。

    第三,您会发现手动绘制单元格的性能要好得多。创建一个自定义视图(添加到内容视图中),覆盖drawRect:,使用UIImage 的drawInRect: 方法在其上绘制图像。这将大大加快速度!尽可能绘制所有内容,因为子视图布局很昂贵!此外,如果可能,请确保不使用 UIView(包括 UIImageView、UILabel 等)透明度,设置 opaque = YES 并设置背景颜色。最好在drawRect: 中绘制文本,使用NSString 的drawInRect: 方法,这将提供透明UILabel 的外观。

    但是,如果您的单元格非常少,例如

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      感谢您的建议迈克尔。我确实可以使用以下代码解决我的图形问题:

      [bubbleView setImage:[bubble stretchableImageWithLeftCapWidth:165 topCapHeight:30]];
      

      我现在可以使用 1 张图片,而不是使用 3 张单独的图片来创建聊天气泡,并且它可以优雅地伸展。确实是一个非常好的建议:)

      尽管我似乎没有太多速度问题,但我确实按照您的建议部分重写了我的代码,主要是通过在代码的单元初始化器部分中构造单元的主要部分。我确实注意到速度略有提高,也许它在设备上更明显(与模拟器相比)。

      目前我仍然使用 ImageView 绘制图像(如您所见),每当我需要更快的渲染速度时,我都会查看 [UIImage drawInRect:]。

      感谢您的建议,非常感谢。

      【讨论】:

      • 欢迎您!是的,我建议定期在设备上进行测试。模拟器非常快,因为它拥有你所有的 mac 内存和 CPU 能力。如果您有相当多的行,我认为您在设备上滚动时会看到较慢的帧速率(与文本消息应用程序或 iPod 应用程序相比)。我最初只使用模拟器花了很多时间,当我最终在设备上进行测试时,一切都非常慢,我不得不重写我所有的表格视图代码! (当然我大量使用它们!)但我已经吸取了教训!祝你好运!
      猜你喜欢
      • 2013-09-27
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      相关资源
      最近更新 更多