0
votes

I'd like to add shadow to a UIImageView which has image layers.

I've tried self.layer.shadowOffset/shadowOpacity route, but it's too slow..
When I want to add a shadow, I call addShadowLayerWithOffset method below which I expected to call drawRect and add shadow..
But drawRect isn't getting called.

What am I missing here?

- (void)drawRect:(CGRect)rect
{
    SYSLOG(LOG_DEBUG, "in drawRect, isShadowed: %d", isShadowed);
    if (isShadowed == true)
    {
        CGContextRef currentContext = UIGraphicsGetCurrentContext();
        CGContextSaveGState(currentContext);
        CGContextSetShadow(currentContext, CGSizeMake(100, 100), 3);
        [super drawRect: rect];
        CGContextRestoreGState(currentContext);
    }
    else
        [super drawRect: rect];
}

- (void) addShadowLayerWithOffset: (int)offset
{
//  self.layer.shadowOffset = CGSizeMake(offset,offset);                                                                                                                                                                                                                      
//  self.layer.shadowOpacity = 0.7f;                                                                                                                                                                                                                                          
//  self.layer.shadowRadius = 5.0;                                                                                                                                                                                                                                            
    isShadowed = true;
    [self setNeedsDisplay];
}
  • EDIT

ok, I got drawLayer being called. I needed [self.layer setNeedsDisplay] not [self.layer setNeedsPlay] where self is the UIImageView subclass.

But shadow is not being drawn, in fact image(original layer) itself is not shown either.
What should I change?

- (void) drawLayer: (CALayer*) layer inContext: (CGContextRef)context
{
    SYSLOG(LOG_DEBUG, "in drawLayer, isShadowed: %d", isShadowed);
    if(isShadowed == true)
    {
        CGContextSaveGState(context);
        CGContextSetShadow(context, CGSizeMake(10, 10), 3);
        [super drawLayer: layer inContext: context];
        CGContextRestoreGState(context);
    }
    else
        [super drawLayer: layer inContext: context];
}
3

3 Answers

2
votes

try to call this method:

called by a UIViewController:

[self addShadowedLayer:self.view inRect:( CGRectMake(30, 30, 128, 192))];


- (void)addShadowedLayer:(UIView *)aUIView inRect:(CGRect)aRect {
    CALayer *sublayer = [CALayer layer];
    sublayer.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;
    sublayer.shadowOffset = CGSizeMake(0, 3);
    sublayer.shadowRadius = 5.0;
    sublayer.shadowColor = [UIColor blackColor].CGColor;
    sublayer.shadowOpacity = 0.8;
    sublayer.frame = aRect;
    sublayer.cornerRadius = 26.0;
    [aUIView.layer addSublayer:sublayer];
}

it just add a white rounded rect, but what you need is just its shadow...

1
votes

you are calling:

[super drawRect: rect];

but apple says:

You should never call this method directly yourself. To invalidate part of your view, and thus cause that portion to be redrawn, call the setNeedsDisplay or setNeedsDisplayInRect: method instead.

instead of drawRect, ever tried drawLayer?

-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
1
votes

I think you are barking up the wrong tree. You said that specifying the shadow directly on the image layer is too slow. That is correct because the OS uses the alpha channel to determine where to draw the shadow.

What you can do to improve the rendering performance on iOS 3.2 and later is that you specify a shadow path. You first create a CGPathRef and set it as the shadow path of the layer.

This should improve rendering dramatically without having you to introduce another layer just for the shadow.