iPhone:向单元格内容视图添加子视图会覆盖滚动时的单元格文本

发布于 2024-11-15 14:51:20 字数 2793 浏览 3 评论 0原文

我在实现中使用了 Cell.ContentView 来自定义单元格内容。它工作正常,但唯一的问题是,当我有很多单元格并且我上下滚动它们时,单元格内容会被覆盖到单元格中,这些单元格变得隐藏,然后变得可见。假设我向上滚动第一个单元格,然后再次将其向下滚动,最后一个单元格的内容将被覆盖在第一个单元格上!

我对此进行了足够的调试,但找不到确切的解决方案。我尝试检查 Cell.ContentView.SubViews 计数,如果为 0,则仅添加其他子视图。在我上下滚动它们之前,它不会显示任何单元格内容,但是一旦内容出现,它就不会覆盖..有点奇怪..!我还确保我正确地重复使用了电池。以下是我的代码,它将子视图添加到单元格的内容视图中。请让我知道如何摆脱这个问题。

PS:不要担心我所做的变量和计算。假设它返回正确的值。 :)

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

    NSInteger totalAvailableSpace = IPHONE_DISPLAY_WIDTH - iconSize - accesorySize - 10;
    NSInteger lableHeight = [[cellDetails objectForKey:@"TableItemTextFontSize"] intValue] * 2 + 10;

    UILabel *textLabel = nil;
    textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+12, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.8, lableHeight)] autorelease];
    textLabel.numberOfLines = 2;
    textLabel.lineBreakMode = UILineBreakModeWordWrap;
    textLabel.textAlignment = UITextAlignmentLeft;
    textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];
    if ([textLableColor scanHexInt:&hex]) {
        textLabel.textColor = UIColorFromRGB(hex);
    }
    textLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemTextFontName"] size:[[cellDetails objectForKey:@"TableItemTextFontSize"] intValue]]; 
    [cell.contentView addSubview:textLabel];
    textLabel.backgroundColor = [UIColor clearColor];

    lableHeight = [[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue] * 2 + 10;
    UILabel *detailTextLabel = nil;
    detailTextLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+10+totalAvailableSpace * 0.8+5, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.2 - 10, lableHeight)] autorelease];
    detailTextLabel.numberOfLines = 2;
    detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
    detailTextLabel.textAlignment = UITextAlignmentLeft;
    detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];
    if ([detailTextLableColor scanHexInt:&hex]) {
        detailTextLabel.textColor = UIColorFromRGB(hex);
    }
    detailTextLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemDetailTextFontName"] size:[[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue]];
    [cell.contentView addSubview:detailTextLabel];
    detailTextLabel.backgroundColor = [UIColor clearColor];

    return cell;
}

谢谢。

I have used Cell.ContentView in my implementation for customizing the cell contents. It works fine but the only problem is when I have many cells and I scroll them up and down, the cell contents gets overwritten into the cells just become hidden followed by visible. Suppose I scroll first cell up and then again takes it down, the last cell's contents gets overwritten on first cell!!

I debugged enough on this but couldn't find the exact solution. I tried checking Cell.ContentView.SubViews count and if it 0 then only add other subviews. This doesn't display any cell contents until I scroll them up and down but once contents appeared, it doesn't overwrite..Little bit strange..!! I also made sure that I am using reusing the cell correctly. Following is my code that adds subviews into cell's contentview. Please let me know how could I get rid of this issue.

P.S: Don't worry about the variables and calculations I have done. Assume that it returns correct values. :)

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

    NSInteger totalAvailableSpace = IPHONE_DISPLAY_WIDTH - iconSize - accesorySize - 10;
    NSInteger lableHeight = [[cellDetails objectForKey:@"TableItemTextFontSize"] intValue] * 2 + 10;

    UILabel *textLabel = nil;
    textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+12, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.8, lableHeight)] autorelease];
    textLabel.numberOfLines = 2;
    textLabel.lineBreakMode = UILineBreakModeWordWrap;
    textLabel.textAlignment = UITextAlignmentLeft;
    textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];
    if ([textLableColor scanHexInt:&hex]) {
        textLabel.textColor = UIColorFromRGB(hex);
    }
    textLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemTextFontName"] size:[[cellDetails objectForKey:@"TableItemTextFontSize"] intValue]]; 
    [cell.contentView addSubview:textLabel];
    textLabel.backgroundColor = [UIColor clearColor];

    lableHeight = [[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue] * 2 + 10;
    UILabel *detailTextLabel = nil;
    detailTextLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+10+totalAvailableSpace * 0.8+5, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.2 - 10, lableHeight)] autorelease];
    detailTextLabel.numberOfLines = 2;
    detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
    detailTextLabel.textAlignment = UITextAlignmentLeft;
    detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];
    if ([detailTextLableColor scanHexInt:&hex]) {
        detailTextLabel.textColor = UIColorFromRGB(hex);
    }
    detailTextLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemDetailTextFontName"] size:[[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue]];
    [cell.contentView addSubview:detailTextLabel];
    detailTextLabel.backgroundColor = [UIColor clearColor];

    return cell;
}

Thanks.

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

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

发布评论

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

评论(5

蘸点软妹酱 2024-11-22 14:51:20

这是因为玩具会一遍又一遍地将视图添加到您的单元格中。

您应该仅在创建单元格时添加它们,并在重用单元格时设置标签。

您可以为标签设置标签,以便之后可以设置它的文本。下面的代码可以解决这个问题

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        if(style == UITableViewCellStyleValue1)
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        else
            cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:CellIdentifier] autorelease];


        NSInteger totalAvailableSpace = IPHONE_DISPLAY_WIDTH - iconSize - accesorySize - 10;
        NSInteger lableHeight = [[cellDetails objectForKey:@"TableItemTextFontSize"] intValue] * 2 + 10;

        UILabel *textLabel = nil;
        textLabel.tag = 1;
        textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+12, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.8, lableHeight)] autorelease];
        textLabel.numberOfLines = 2;
        textLabel.lineBreakMode = UILineBreakModeWordWrap;
        textLabel.textAlignment = UITextAlignmentLeft;
        textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];
        if ([textLableColor scanHexInt:&hex]) {
            textLabel.textColor = UIColorFromRGB(hex);
        }
        textLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemTextFontName"] size:[[cellDetails objectForKey:@"TableItemTextFontSize"] intValue]]; 
        [cell.contentView addSubview:textLabel];
        textLabel.backgroundColor = [UIColor clearColor];

        lableHeight = [[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue] * 2 + 10;
        UILabel *detailTextLabel = nil;
        detailTextLabel.tag = 2;
        detailTextLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+10+totalAvailableSpace * 0.8+5, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.2 - 10, lableHeight)] autorelease];
        detailTextLabel.numberOfLines = 2;
        detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
        detailTextLabel.textAlignment = UITextAlignmentLeft;
        detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];
        if ([detailTextLableColor scanHexInt:&hex]) {
            detailTextLabel.textColor = UIColorFromRGB(hex);
        }
        detailTextLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemDetailTextFontName"] size:[[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue]];
        [cell.contentView addSubview:detailTextLabel];
        detailTextLabel.backgroundColor = [UIColor clearColor];

    } else {

        UILabel *textLabel = (UILabel *)[cell viewWithTag:1];
        textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];

        UILabel *detailTextLabel = (UILabel *)[cell viewWithTag:2];
        detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];

    }

    return cell;
}

That is because toy are adding the views to your cell over and over again.

You should only add them when you create the cell and just set the labels when the cell is being reused.

You could set tags for your label, so that you can set it texts afterwards. The code bellow does the trick

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        if(style == UITableViewCellStyleValue1)
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        else
            cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:CellIdentifier] autorelease];


        NSInteger totalAvailableSpace = IPHONE_DISPLAY_WIDTH - iconSize - accesorySize - 10;
        NSInteger lableHeight = [[cellDetails objectForKey:@"TableItemTextFontSize"] intValue] * 2 + 10;

        UILabel *textLabel = nil;
        textLabel.tag = 1;
        textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+12, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.8, lableHeight)] autorelease];
        textLabel.numberOfLines = 2;
        textLabel.lineBreakMode = UILineBreakModeWordWrap;
        textLabel.textAlignment = UITextAlignmentLeft;
        textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];
        if ([textLableColor scanHexInt:&hex]) {
            textLabel.textColor = UIColorFromRGB(hex);
        }
        textLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemTextFontName"] size:[[cellDetails objectForKey:@"TableItemTextFontSize"] intValue]]; 
        [cell.contentView addSubview:textLabel];
        textLabel.backgroundColor = [UIColor clearColor];

        lableHeight = [[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue] * 2 + 10;
        UILabel *detailTextLabel = nil;
        detailTextLabel.tag = 2;
        detailTextLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+10+totalAvailableSpace * 0.8+5, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.2 - 10, lableHeight)] autorelease];
        detailTextLabel.numberOfLines = 2;
        detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
        detailTextLabel.textAlignment = UITextAlignmentLeft;
        detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];
        if ([detailTextLableColor scanHexInt:&hex]) {
            detailTextLabel.textColor = UIColorFromRGB(hex);
        }
        detailTextLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemDetailTextFontName"] size:[[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue]];
        [cell.contentView addSubview:detailTextLabel];
        detailTextLabel.backgroundColor = [UIColor clearColor];

    } else {

        UILabel *textLabel = (UILabel *)[cell viewWithTag:1];
        textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];

        UILabel *detailTextLabel = (UILabel *)[cell viewWithTag:2];
        detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];

    }

    return cell;
}
や三分注定 2024-11-22 14:51:20
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];

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

确保 dequeueReusableCellWithIdentifier 和 reuseIdentifier 应该为 nil

现在它可以工作了!

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];

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

Make sure that dequeueReusableCellWithIdentifier and reuseIdentifier should be nil

Now it will work !!

吻风 2024-11-22 14:51:20

将所有单元格 UI 内容放入 if(cell==nil){uilabel,uilabel or everythingUI related} ...因为 ui 在创建 cel 时应该只调用一次

Place all the cell UI content inside if(cell==nil){uilabel,uilabel or anythingUI related} ...since ui should be call only once at time of creating cel

蓝海 2024-11-22 14:51:20

需要明确的是,您的问题是,当您将单元格滚动到视图中时,您经常会发现新单元格的文本被写在刚刚滚动到屏幕外的单元格的顶部?

问题是 dequeueReusableCellWithIdentifier: 不会“清理”单元格(它调用 prepareForReuse,但仅此而已),因此所有旧的子视图仍然存在。如果您要重用单元格,则不应每次都重新创建这些子视图。相反,只需调整从 dequeueReusableCellWithIdentifier: 返回的单元格上现有子视图的属性,并仅在新分配的单元格上创建新的子视图。子类化 UITableViewCell 可以帮助解决这个问题,既可以提供属性/ivars来保存对这些子视图的引用,也可以通过将子视图的创建和更新移到适当的方法中来更好地组织代码。或者您可以通过传递 nil 作为重用标识符来不重用单元。

在您上下滚动之前它不显示任何内容的最可能的原因是新创建的单元格可能具有框架提供的文本字段和图像视图,如果框架确定您不这样做,则可能会删除它们实际上并没有使用它们。

To be clear, your problem is that as you scroll a cell into view you will often wind up with the text of the new cell being written over the top of a cell that was just scrolled offscreen?

The problem is that dequeueReusableCellWithIdentifier: doesn't "clean up" the cell (it calls prepareForReuse, but that's it), so all your old subviews are still in place. If you are going to reuse cells, you shouldn't be recreating these subviews each time. Instead, just adjust the properties of the existing subviews on a cell you get back from dequeueReusableCellWithIdentifier:, and only create the new subviews on a newly-allocated cell. Subclassing UITableViewCell can help with this, both to provide properties/ivars in which to hold references to these subviews and to organize the code a little nicer by moving the creation of subviews and the updating into appropriate methods. Or you could just not reuse cells, by passing nil for the reuse identifier.

The most likely reason that it didn't display any content until you scroll up and down is that a newly-created cell may have the framework-provided text field and image view, which may then be removed if the framework determines that you aren't actually using them.

绮烟 2024-11-22 14:51:20

在 iOS5 中,UILineBreakModeWordWrap 已弃用。您应该使用 NSLineBreakByWordWrapping 来代替。

这会将您的代码更改为 detailTextLabel.lineBreakMode = NSLineBreakByWordWrappingtextLabel.lineBreakMode = NSLineBreakByWordWrapping

In iOS5 UILineBreakModeWordWrap is deprecated. You should use NSLineBreakByWordWrapping instead.

This would change you code to look like detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping and textLabel.lineBreakMode = NSLineBreakByWordWrapping.

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