Adding multiple shadows to a UIView in either Objective-C or Swift


Alex Zavatone
 

Has any one of of us successfully done this?  We’ve been trying to do this with CALayers for days now and it’s been monumentally unsuccessful.

Either we get one shadow on one layer and no shadows on any other added layer or no shadows at all.  I’ll gladly post code, but we’ve been at this for way too long and with too many iterations.  

We’ve been inserting and adding layers and it’s pretty odd just how this goes to extreme efforts not to produce any additional shadows.

Also, when inserting a CALayer at an index, the docs are really good at not stating what the layer stands for.  Is it a Z-order?  What does position 0 represent?  Frontmost?  Bottom?  Nothing related to the above?

Thanks in advance.  I’ve done this in Obj-C and Swift it’s amazing how hard it is to get a second layer to not replace the previous one and to get a shadow on both.  

Here’s some Obj-C code that I am using to set a shadow.

If I take that code below and change it to add a shadow to a layer and return the layer, then insert or add it to the view, we get nothing but the code below works fine on its own.  

alpha = 0.4;
    x = 0;
    y = 8.0;
    blur = 10.0;
    spread = 10.0; // 1

    

    [self.box2 addShadowToView:color alpha:alpha x:x y:y blur:blur spread:spread];

——––––

- (UIView *)addShadowToView:(UIColor *)color
                  alpha:(CGFloat)alpha
                      x:(CGFloat)x
                      y:(CGFloat)y
                   blur:(CGFloat)blur
                 spread:(CGFloat)spread
{

    

    self.layer.masksToBounds = NO;
    self.layer.needsDisplayOnBoundsChange = YES;
    self.layer.shouldRasterize = YES;
    self.layer.shadowColor = color.CGColor;
    self.layer.shadowOpacity = alpha;
    self.layer.shadowOffset = CGSizeMake(x, y);
    self.layer.shadowRadius = blur / 2 ; //UIScreen.mainScreen.scale;
    if (spread == 0) {
        self.layer.shadowPath = nil;
    } else {
        CGFloat deltaX = spread;
        CGRect shadowRect = CGRectInset(self.bounds, deltaX, deltaX);
        self.layer.shadowPath = CFBridgingRetain([UIBezierPath bezierPathWithRect: shadowRect]);
    }

    

    return self;
}







Alex Zavatone
 

Apparently, layers do now render shadows at all if the layer is of clearColor.

There is a second layer in the image below, but no shadow.


Now, how to work around that?


On Jun 16, 2021, at 9:46 AM, Alex Zavatone via groups.io <zav@...> wrote:

Has any one of of us successfully done this?  We’ve been trying to do this with CALayers for days now and it’s been monumentally unsuccessful.

Either we get one shadow on one layer and no shadows on any other added layer or no shadows at all.  I’ll gladly post code, but we’ve been at this for way too long and with too many iterations.  

We’ve been inserting and adding layers and it’s pretty odd just how this goes to extreme efforts not to produce any additional shadows.

Also, when inserting a CALayer at an index, the docs are really good at not stating what the layer stands for.  Is it a Z-order?  What does position 0 represent?  Frontmost?  Bottom?  Nothing related to the above?

Thanks in advance.  I’ve done this in Obj-C and Swift it’s amazing how hard it is to get a second layer to not replace the previous one and to get a shadow on both.  

Here’s some Obj-C code that I am using to set a shadow.

If I take that code below and change it to add a shadow to a layer and return the layer, then insert or add it to the view, we get nothing but the code below works fine on its own.  

alpha = 0.4;
    x = 0;
    y = 8.0;
    blur = 10.0;
    spread = 10.0; // 1
    
    [self.box2 addShadowToView:color alpha:alpha x:x y:y blur:blur spread:spread];

——––––

- (UIView *)addShadowToView:(UIColor *)color
                  alpha:(CGFloat)alpha
                      x:(CGFloat)x
                      y:(CGFloat)y
                   blur:(CGFloat)blur
                 spread:(CGFloat)spread
{
    
    self.layer.masksToBounds = NO;
    self.layer.needsDisplayOnBoundsChange = YES;
    self.layer.shouldRasterize = YES;
    self.layer.shadowColor = color.CGColor;
    self.layer.shadowOpacity = alpha;
    self.layer.shadowOffset = CGSizeMake(x, y);
    self.layer.shadowRadius = blur / 2 ; //UIScreen.mainScreen.scale;
    if (spread == 0) {
        self.layer.shadowPath = nil;
    } else {
        CGFloat deltaX = spread;
        CGRect shadowRect = CGRectInset(self.bounds, deltaX, deltaX);
        self.layer.shadowPath = CFBridgingRetain([UIBezierPath bezierPathWithRect: shadowRect]);
    }
    
    return self;
}








Carl Hoefs
 

In past code, I've used the behavior that layers will render a shadow whose strength is in accord with the opacity of the fill color. 0 opacity (clearColor) gives no shadow at all.

I think you may be fighting the frameworks here...

-Carl

On Jun 16, 2021, at 8:33 AM, Alex Zavatone via groups.io <zav@...> wrote:

Apparently, layers do now render shadows at all if the layer is of clearColor.


Alex Zavatone
 

Well, it sure is an important detail.  If no color is added or if you use a clear color, you get no shadow.  

I did find a sort of a solution though and this works as long as you don’t have a transparency on the image.  

Duplicate the CALayer.

But that’s the problem?  How? 

Through NSKeyedArchiver or CAReplicatorLayer.

CALayer *layer1;
CALayer *layer2;

// Set up layer1's specifics.

layer2 = [NSKeyedUnarchiver unarchivedObjectOfClass:[CALayer class]
                                                            fromData:[NSKeyedArchiver archivedDataWithRootObject:layer1 requiringSecureCoding:NO error:nil] error:nil];

Two shadows on one UIView with 2 layers.  Testing now with PNG and SVG images.

This also works.

Cheers and if anyone wants the code when I’m done, I’ll happily share it.

Alex Zavatone



On Jun 16, 2021, at 10:40 AM, Carl Hoefs <newslists@...> wrote:

In past code, I've used the behavior that layers will render a shadow whose strength is in accord with the opacity of the fill color. 0 opacity (clearColor) gives no shadow at all.

I think you may be fighting the frameworks here...

-Carl


On Jun 16, 2021, at 8:33 AM, Alex Zavatone via groups.io <zav@...> wrote:

Apparently, layers do now render shadows at all if the layer is of clearColor.