在重复使用的原型单元格中多次应用渐变蒙版

时间:2015-10-10 09:45:56

标签: ios objective-c xcode xcode-storyboard

我有一个tableview,有一个客户UITableViewCell类 - 这是在Storyboard / Builder中创建的原型单元格。

因为我的单元格链接到Storyboard原型,所以我按如下方式引用它(cellIdentifier匹配原型单元格上的ID):

EventsListTableViewCell *cell = (EventsListTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

因此,单元格始终已初始化并准备就绪(我无法使用" if(cell == nil {...}")

这很好,但是我想在我的单元格中添加一个渐变图层,我在cellForRowAtIndex中做了一遍:

gradientMask = [CAGradientLayer layer];
gradientMask.frame = cell.eventImage.layer.bounds;

gradientMask.startPoint = CGPointMake(0.5, 0.2);
gradientMask.endPoint = CGPointMake(0.5, 1.0);
gradientMask.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                       (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
[cell.eventImage.layer insertSublayer:gradientMask atIndex:0];

这里的问题是,每次重复使用细胞时都会应用gradientMask,因此当我向下滚动时会变暗和变暗

我意识到我需要在第一次创建单元格时才应用此gradientMask一次,但是我不知道在哪里调用此代码,因为我从来没有“初始化”。单元格(由故事板处理)

我确实有一个这个单元格的自定义类,但它只包含属性而没有方法?

2 个答案:

答案 0 :(得分:3)

有多种方法可以实现这一目标:

1- UITableViewCell子类中的属性

在EventsListTableViewCell类中创建一个属性,该属性将包含对gradientMask的引用:

@interface EventsListTableViewCell : UITableViewCell

@property (weak, nonatomic) CAGradientLayer *gradientMask;

@end

然后在cellForRowAtIndexPath:方法中:

if (!cell.gradientMask) {
    gradientMask = [CAGradientLayer layer];
    gradientMask.frame = cell.eventImage.layer.bounds;

    gradientMask.startPoint = CGPointMake(0.5, 0.2);
    gradientMask.endPoint = CGPointMake(0.5, 1.0);
    gradientMask.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
    [cell.eventImage.layer insertSublayer:gradientMask atIndex:0];
    cell.gradientMask = gradientMask;
}

这将确保gradientMask仅初始化一次。

CALayer 的<{3}}

这样,您就不需要创建属性,所有内容都可以在cellForRowAtIndexPath:方法本身中处理。

BOOL gradientFound = NO;

for (CALayer *layer in cell.eventImage.layer.sublayers)
{
    if ([layer.name isEqualToString:@"gradientLayer"])
    {
        gradientFound = YES;
        break;
    }
}

if (!gradientFound)
{
    gradientMask = [CAGradientLayer layer];
    gradientMask.frame = cell.eventImage.layer.bounds;
    gradientMask.name = @"gradientLayer";               //Set the name
    gradientMask.startPoint = CGPointMake(0.5, 0.2);
    gradientMask.endPoint = CGPointMake(0.5, 1.0);
    gradientMask.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
    [cell.eventImage.layer insertSublayer:gradientMask atIndex:0];

}

3-在UITableViewCell子类本身中声明gradienLayer

这是最干净的方式,因为它还隔离了与其类别中的单元格相关的代码。您可以使用awakeFromNib方法初始化单元格。

@implementation EventsListTableViewCell
{
    CAGradientLayer *gradientMask;
}

-(void)awakeFromNib
{
    gradientMask = [CAGradientLayer layer];
    gradientMask.frame = cell.eventImage.layer.bounds;

    gradientMask.startPoint = CGPointMake(0.5, 0.2);
    gradientMask.endPoint = CGPointMake(0.5, 1.0);
    gradientMask.colors = [NSArray arrayWithObjects:
                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.0f] CGColor],

                           (id)[[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f] CGColor],nil];
    [self.eventImage.layer insertSublayer:gradientMask atIndex:0];
}

@end

答案 1 :(得分:0)

由于您自己在故事板文件中添加了此图层,因此将在cellReuse周期内删除此图层。你必须手动完成。
我通常为单元格创建一个子类并覆盖prepareForReuse方法,在那里我删除了我在那里添加的所有自定义视图和图层。这样一切都会顺利进行 不要忘记将您的子视图添加到单元格的contentView属性中。