将滚动后的CALayer添加到UITableViewCell中

时间:2014-01-24 21:02:43

标签: ios objective-c uitableview calayer

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

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

2 个答案:

答案 0 :(得分:4)

GACK! NOT 为每个单元格使用不同的单元格标识符。这完全打败了细胞重用机制,并且会为你提供不断增加的内存使用,并迫使你总是为每个索引创建一个新的细胞 - 最糟糕的结果。

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

这有点像医生的办公室,有耐心的表格供你填写。你填写一份表格并交给店员。职员将信息键入计算机,然后将表单放回到空白表格的顶部。下一位患者必须从表格中删除所有内容,包括孩子的姓名,如果他们没有任何孩子,配偶,他们没有的预先存在的条件等等。否则,最后一个人使用的信息表单仍将在您的表单上。

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

答案 1 :(得分:3)

事实证明,删除它的原因是CALayer被添加到单元格而不是UITableViewCell contentView。所以正确的实现如下:

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