【问题标题】:Adding CALayer to UITableViewCell removed after scroll滚动后删除将 CALayer 添加到 UITableViewCell
【发布时间】:2014-02-16 00:32:50
【问题描述】:

我正在尝试在 UITableViewCell 的底部添加一个 CALayer 以获得一点“阴影”效果。问题是当表格向上滚动并离开屏幕时,图层被删除,因此当您向下滚动时它不可见。如果您将单元格向下滚动到屏幕之外,然后将它们备份起来,它们看起来很好。

I have a gif here showing what's happening.

这就是我的做法:

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


    static NSString *cellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

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

    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", (int)indexPath.row];

    CALayer *bottomBorder = [CALayer layer];
    bottomBorder.frame = CGRectMake(0.0f, cell.frame.size.height, cell.frame.size.width, 1.0f);
    bottomBorder.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor;
    [cell.layer addSublayer:bottomBorder];

    cell.clipsToBounds = NO;

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

我也尝试为每个单元格使用一个唯一的 cellIdentifier,希望它们不会被重用,因此该层永远不会像这样删除:

    //Same code as before just this changed
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"%ld_%ld", (long)indexPath.row, (long)indexPath.section]];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:@"%ld_%ld", (long)indexPath.row, (long)indexPath.section]];
    }

    //Same code continued...

所以我的问题是,当一个单元格被重用时,添加到它的 CALayer 被删除了。当单元格从屏幕上滚动并重新打开时,我需要做什么才能将该层保留在那里。

编辑:

我也试过这个也不起作用:

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


    static NSString *cellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

        CALayer *bottomBorder = [CALayer layer];
        bottomBorder.frame = CGRectMake(0.0f, cell.frame.size.height, cell.frame.size.width, 1.0f);
        bottomBorder.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor;
        [cell.layer addSublayer:bottomBorder];

        cell.clipsToBounds = NO;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }

    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", (int)indexPath.row];

    return cell;
}

【问题讨论】:

    标签: ios objective-c uitableview calayer


    【解决方案1】:

    原来它被删除的原因是CALayer被添加到单元格而不是UITableViewCellcontentView。所以正确的实现如下:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    
        static NSString *cellIdentifier = @"CellIdentifier";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
            CALayer *bottomBorder = [CALayer layer];
            bottomBorder.frame    = CGRectMake(0.0f,
                                               (CGRectGetHeight(cell.contentView.bounds) - 1),
                                               CGRectGetWidth(cell.contentView.bounds),
                                               1.0f);
    
            bottomBorder.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor;
            [cell.contentView.layer addSublayer:bottomBorder];
        }
    
        cell.textLabel.text = [NSString stringWithFormat:@"Row %d", (int)indexPath.row];
    
        return cell;
    }
    

    【讨论】:

      【解决方案2】:

      盖克!请为每个单元格使用不同的单元格标识符。这完全破坏了单元重用机制,并且会给您带来不断增加的内存使用并迫使您始终为每个索引创建一个新单元 - 这是最糟糕的结果。

      每次单元格滚动到屏幕外时,它都会进入重用队列。然后,当一个新的索引路径滚动到视图中时,系统会从回收站中取出一个以前使用过的单元格并将其交给您。您应该假设它的 STRUCTURE 已完全形成(您添加的任何自定义字段都将存在)但内容都错误,需要完全设置。因此,如果您有一个带有 3 个标签的单元格,并且模型中的一些对象将文本填充到 1 个标签中,一些对象填充到 2 个标签中,一些对象填充到所有 3 个标签中,您应该始终为所有 3 个标签设置一个值,即使它是空的细绳。这可以防止上次使用单元格时留下的值留在周围。

      这有点像医生办公室,里面有患者表格供您填写。您填写表格并将其交给店员。职员将信息输入计算机,然后将表格放回空白表格的顶部。下一位患者必须从表格中删除所有内容,包括孩子的姓名(如果他们没有孩子的话)、配偶、他们没有的既往疾病等等。否则,来自最后一个使用该表格的人的信息表单仍会在您的表单上。

      至于您的阴影层,当您使用 dequeueReusableCellWithIdentifier 获取一个单元格时,您应该只在必须创建一个新单元格时添加您的层。如果您取回一个重复使用的单元格,则该图层已经存在,但如果它们从一个单元格更改为另一个单元格,您可能需要设置它的内容。

      【讨论】:

      • 感谢您抽出宝贵时间回答。我完全理解 UITableView 如何重用单元格。我所做的只是试图以某种形式解决问题,即使错误的方法只是为了让它进入工作状态。我更新了我的问题,更明确地定义了我要问的内容。
      • 除非你贴的代码有误。向单元格添加层的代码属于“if (!cell)”条件。相反,每次你重复使用一个单元格时,你都会向它添加一个新层,这很糟糕。这告诉我,您并不像您认为的那样了解单元重用。
      • 我想我应该发布我尝试过的所有代码。将其放入 if (!cell) 也不能解决问题。
      猜你喜欢
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多