I' m trying to subclass CALayer
for use as a mask on another layer.
I want to use my CALayer
subclass in place of a CAGradientLayer
and use it for a gradient mask as explained here.
However I wish to use a custom CALayer
that uses an internal CGGradient
for drawing instead, as this should produce smoother results than CAGradientLayer
(see here). I don't care about performance, I want better gradient quality.
I'm following this example for creating my CGGradient
and storing it on the CALayer
.. However, I cannot get the mask to draw.
I don't know where to put the draw code: CALayer
's display
nor drawInContext:(CGContextRef)ctx
nor drawInContext:(CGContextRef)ctx
seem to be called when it is used as a mask.
Bear with me as I'm new with CoreAnimation. So, how to fix this so my CALayer
subclass works as a replacement for CAGradientLayer
but draws using a CGGradient
?
My current code here:
@interface CANiceGradientLayer : CALayer
@property (nonatomic) CGGradientRef gradient;
@property (atomic) CGPoint startPoint;
@property (atomic) CGPoint endPoint;
@end
@implementation CANiceGradientLayer
- (instancetype)initWithGradientRef:(CGGradientRef)gradient startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint
{
if ( !(self = [super init]) )
{
return nil;
}
self.gradient = CGGradientRetain(gradient);
self.startPoint = startPoint;
self.endPoint = endPoint;
return self;
}
- (void)dealloc
{
CGGradientRelease(self.gradient);
}
- (void)display
{
NSLog(@"display");
}
- (void)drawInContext:(CGContextRef)ctx
{
NSLog(@"drawInContext:");
CGContextDrawLinearGradient(ctx, self.gradient, self.startPoint, self.endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);;
}
- (void)renderInContext:(CGContextRef)ctx
{
NSLog(@"renderInContext:");
}
@end
And here is how I create it:
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 1.0, // Start color
1.0, 1.0, 1.0, 0.0 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
self.collectionViewTickerMaskLayer = [[CANiceGradientLayer alloc] initWithGradientRef:gradient startPoint:CGPointZero endPoint:CGPointZero];
self.collectionViewTickerMaskLayer.anchorPoint = CGPointZero;
view.layer.mask = self.collectionViewTickerMaskLayer;
If I use a CAGradientLayer
instead, it works fine (but the gradient looks bad).