如何将CALayer子类化为另一个CALayer掩码?

时间:2014-07-13 15:33:23

标签: ios objective-c uiview core-graphics core-animation

我正在尝试将CALayer子类化为另一层的掩码。

我想使用我的CALayer子类代替CAGradientLayer,并将其用作渐变蒙版,如here所述。

但是,我希望使用使用内部CALayer进行绘制的自定义CGGradient,因为这会产生比CAGradientLayersee here)更平滑的结果。我不关心性能,我想要更好的渐变质量。

我正在关注this example创建我的CGGradient并将其存储在CALayer上。但是,我无法绘制掩码。

我不知道在哪里放置绘图代码:CALayer的{​​{1}},displaydrawInContext:(CGContextRef)ctx似乎在用作面具时被调用

请耐心等待我,因为我是CoreAnimation的新手。那么,如何解决这个问题,以便我的drawInContext:(CGContextRef)ctx子类可以替代CALayer但是使用CAGradientLayer进行绘制?


我目前的代码:

CGGradient

以下是我创建它的方式:

@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

如果我使用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; 代替,它可以正常工作(但渐变看起来很糟糕)。

1 个答案:

答案 0 :(得分:2)

在将图层子类设置为蒙版之前调用图层子类上的-setNeedsDisplay,并且您只需要覆盖-drawInContext:子类的CALayer。这将帮助您获取要调用的方法(CALayer使用-drawInContext:之后调用的-display默认实现来调用-setNeedsDisplay。您可能还需要设置图层的框架:

self.collectionViewTickerMaskLayer.frame = view.layer.bounds;
self.collectionViewTickerMaskLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;

此代码中存在逻辑问题。您使用的是CGPointZero端点,因此即使调用这些方法,也不会绘制任何渐变来掩盖您的图层。