在重用的原型单元格中多次应用渐变蒙版
Gradient Mask is applied multiple times in reused prototype cell
我有一个带有客户 UITableViewCell class 的表格视图 - 这是在 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 一次,但是我不确定在哪里调用此代码,因为我从来没有 'init' 单元格(这是由故事板)
我确实有这个单元格的自定义 class,但它只包含属性而没有方法?
有多种实现方法:
1- 属性 in UITableViewCell subclass
在 EventsListTableViewCell class 中创建一个 属性,它将保存对 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 仅初始化一次。
2-name property共CALayer
这样,您就不需要创建 属性,一切都可以在 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 subclass 本身中声明 gradienLayer
这是最简洁的方法,因为它还将与单元格相关的代码隔离在 class 中。您可以在 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
由于您是自己从故事板文件中添加这一层,因此在 cellReuse
周期内该层将被删除。你必须手动完成。
我通常为单元格创建一个子类并覆盖 prepareForReuse
方法,在该方法中我删除了我在那里添加的所有自定义视图和图层。这样一切都会顺利进行。
并且不要忘记将您的子视图仅添加到单元格的 contentView
属性。
我有一个带有客户 UITableViewCell class 的表格视图 - 这是在 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 一次,但是我不确定在哪里调用此代码,因为我从来没有 'init' 单元格(这是由故事板)
我确实有这个单元格的自定义 class,但它只包含属性而没有方法?
有多种实现方法:
1- 属性 in UITableViewCell subclass
在 EventsListTableViewCell class 中创建一个 属性,它将保存对 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 仅初始化一次。
2-name property共CALayer
这样,您就不需要创建 属性,一切都可以在 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 subclass 本身中声明 gradienLayer
这是最简洁的方法,因为它还将与单元格相关的代码隔离在 class 中。您可以在 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
由于您是自己从故事板文件中添加这一层,因此在 cellReuse
周期内该层将被删除。你必须手动完成。
我通常为单元格创建一个子类并覆盖 prepareForReuse
方法,在该方法中我删除了我在那里添加的所有自定义视图和图层。这样一切都会顺利进行。
并且不要忘记将您的子视图仅添加到单元格的 contentView
属性。