表视图出列可重用单元格重叠

Posted

技术标签:

【中文标题】表视图出列可重用单元格重叠【英文标题】:tableview dequeue reusable cell overlaps 【发布时间】:2015-04-09 00:47:30 【问题描述】:

我有一个自定义表格视图单元格类。我动态地创建 uiviews 和 uilabels 和 uiimageview 到单元格和分配并使用 frame.contentView 初始化它们。但是在滚动时,由于重用,它们会重叠,标签的文本和其他属性也会重叠。

【问题讨论】:

能否请您澄清一下,单元格是否相互重叠,或者标签和 uiimageviews 是否在一个单元格中多次出现? 重叠并看到额外的视图,以防前一个单元格确实添加了额外的视图而后者的视图较少 【参考方案1】:

如果您重复使用单元格,您几乎完全负责在重复使用之前重置其内容。在我看来,这个问题在 SDK 文档中仍未得到充分解释。

这意味着,在调用 [dequeueReusableCellWithIdentifier] 之后,您应该执行以下操作:

1) 设置/重置 textLabel 和 detailTextLabel 上的颜色、字体和文本,如果你曾经触摸过这些。

2) 调整附件类型。

3) 调整边框和背景颜色。

4) 移除所有非标准子视图。我通常这样编码:

for (UIView *subView in cell.contentView.subviews) 
    if (subView == cell.textLabel) continue;
    if (subView == cell.imageView) continue;
    if (subView == cell.detailTextLabel) continue;
    [subView removeFromSuperview];

等等。对于特定的重用标识符,可以触及的任何内容都应重置为零状态。

【讨论】:

不幸的是,我没有任何 cell.textlabel 或任何其他变量。我使用 for 循环根据需要添加子视图。并且每次都分配它们。 这些只是示例。尝试 4) 中的代码,该代码在添加新子视图之前删除所有额外的子视图。【参考方案2】:

检查表格的行大小和自定义单元格的行大小应该相同才能获得正确的视图。

重用tabeview单元后像这样检查和分配单元。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 
   static NSString *cellIdentifier = @"SampleCell";

   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil) 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
    NSLog(@"cai no init da cell");
// change style according to yours..


return cell

【讨论】:

【参考方案3】:

听起来您正在向tableview:cellForRowAtIndexPath: 方法内的单元格添加子视图。在重复使用单元格时,单元格中已经存在之前使用的视图,您将忽略这些新视图并添加更多视图。

正确的方法是在初始化单元格的过程中添加视图,然后在tableview:cellForRowAtIndexPath:方法中设置视图的值。

您应该使用继承自 UITableViewCell 的自定义类并为要添加的视图创建属性(以便可以在tableview:cellForRowAtIndexPath: 中访问它们)。然后,您可以在自定义类的 init 调用中添加视图,或者使用 XIB 或原型单元添加视图并将它们作为 IBOutlets 连接到属性。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    MyModelObject* myObject = myObjects[indexPath.row];

    if (myObject.images.count == 1) 
        MyCustomTableViewCellOne *cell = (MyCustomTableViewCellOne*) [self.tableView dequeueReusableCellWithIdentifier:@"MyCustomTableViewCellOneIdentifer" forIndexPath:indexPath]; 

        cell.title = @"Some item";
        cell.imageView.image = [UIImage imageNamed:@"image.png"];
        return cell;
     else 
        MyCustomTableViewCellTwo *cell = (MyCustomTableViewCellTwo) [self.tableView dequeueReusableCellWithIdentifier:@"MyCustomTableViewCellTwoIdentifer" forIndexPath:indexPath]; 

        cell.title = @"Some item";
        cell.imageView.image = [UIImage imageNamed:@"image.png"];
        cell.imageView2.image = [UIImage imageNamed:@"image2.png"];
        return cell;
    

MyCustomTableViewCellOne.h:

@interface MyCustomTableViewCellOne : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *title;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;

@end

MyCustomTableViewCellTwo.h:

@interface MyCustomTableViewCellTwo : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *title;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) IBOutlet UIImageView *imageView2;

@end

【讨论】:

但是如何创建属性?对于一个单元格,我想为其他单元格添加 4 个子视图和 2 个子视图。子视图的数量不固定。 如果您想要使用几种不同的布局,请为每个布局创建原型单元格和自定义类。如果要创建的单元格太多或者每次都会有所不同,那么正如@rkunde 建议的那样,也许最好的方法是每次通过删除所有子视图来重置单元格。 如果您使用自定义类方法,我已经用一些示例代码更新了我的解决方案。您将需要替换用于确定使用哪种细胞类型的逻辑。 完全是@JoGoFo,如果我在一个单元格中有 100 个图像视图,而在另一个单元格中有 200 个呢?【参考方案4】:

最后通过为每个子视图使用标签解决了这个问题。从它的父视图按标签获取视图后,如果视图不存在,那么我重新分配并添加SubView。这解决了问题。

【讨论】:

以上是关于表视图出列可重用单元格重叠的主要内容,如果未能解决你的问题,请参考以下文章

无法从出列可重用 UITableViewCell 加载自定义单元格

在运行时重用具有动态布局内容的单元格

由于可重用性问题,tableview 单元格上的图像重复

自定义表格单元重用/出列

从可重用单元中出列时,自定义 CollectionViewCell 上会触发啥方法?

自动布局不适用于可重用的表格视图单元格