UITableView 有一个“丑陋”的地方动态高度行的背景图像

发布于 2024-08-18 04:55:12 字数 3095 浏览 5 评论 0原文

我创建了一个 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;
}

正如您可能注意到的,我使用一个名为 SessionData 的单独类作为 UITableViewDatasource。在 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;
}

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

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

I've created a UITableViewController which calculates the height for each row depending on the amount of text it contains. The code to calculate the row height looks like this:

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

As you might notice, I use a separate class as UITableViewDatasource called SessionData. Inside the SessionData class I draw the rows. Each row has a top image, center image (which is repeated depending on the row height) and bottom image. My problem is the following: the center image is drawn a bit darker then the bottom and top images. My guess is this has something to do with the repeating nature of the image, as the top and bottom images are drawn fine. The following code is part of my [tableView:cellForRowAtIndexPath:] message:

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

My guess is I would need to create a containerView with the total size (width, height) for the top, center and bottom imageViews and add the containerView to the cell, but this didn't seem to work. Anyone have any idea on how to fix this problem?

PLEASE NOTE: My UITableViewController has a gradient as background image. So the top / center / bottom images are drawn on top of the background gradient. Perhaps this is part of the problem as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

后eg是否自 2024-08-25 04:55:12

这里有几点需要注意。

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

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

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

其次,您可能希望查看 可拉伸图像

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

但是,如果您的单元格非常少,例如 < 4什么的,那么可能是画法太多了。不过,还是非常建议!

希望这有帮助!

A few things to note here.

Firstly, there's a lot of processing going on in your cells which will cause very poor scrolling performance on the device. You should make better use of requeuing cells and performing most of the cell setup that's common to all the cells here:

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

That way cell's and their subviews can be reused instead of recreated every time a cell appears on screen (use the tag properties and viewWithTag: methods of views).

Secondly, you may wish to look at stretchable images.

Thirdly, you will notice much better performance by manually drawing cells. Create a custom view (which you add to the content view), override drawRect:, draw images onto them using UIImage's drawInRect: method. This will speed things up significantly! Draw everything you can because subview laying out is expensive! Also, ensure you use no UIView (inc. UIImageView, UILabel, etc...) transparency if possible, set opaque = YES and set background colors. It is preferable to draw text in drawRect:, using NSString's drawInRect: method which will give the look of a transparent UILabel.

However, if you have VERY few cells, like < 4 or something, then perhaps the drawing method is too much. However, it is still very much advised!

Hope this helps!

少女净妖师 2024-08-25 04:55:12

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

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

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

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

目前我仍然使用 ImageView 绘制图像(正如您可能注意到的那样),每当我需要更快的渲染速度时,我都会查看 [UIImage drawInRect:] 。

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

Thanks for your suggestions Michael. I could indeed fix my graphic issues by using the following code:

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

Instead of using 3 separate images to create chat bubbles I can now use 1 image and it stretches gracefully. A very nice suggestion indeed :)

Even though I didn't seem to have much speed issues, I did rewrite my code partially as you suggested, mainly by constructing the main part of the cells in the cell initializer part of the code. I did notice a minor speed improvement, perhaps it's more noticeable on a device (as compared to the simulator).

Currently I still draw my images using ImageView (as you might notice), I'll look at [UIImage drawInRect:] whenever I need more speed in rendering.

Thanks for your suggestions, much appreciated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文