Layers and shadows. Is it possible to have a layer with a shadow and no background color?


Alex Zavatone
 

In my experiments, I noticed that if you simply create a layer for a view and attempt to add a shadow, nothing appears.

Unless some color is applied to the border or the backgroundColor of the layer, no shadow will appear. 

If clearColor is used for the background, then no shadow will appear.

Yet, if you add any pixel to it or a border, the shadow will appear.

I’m specifically applying a rectangular shadow to the layer through a bezier path.

Does anyone know what the minimum settings required on a layer for it to be able to display a shadow?

Assuming that you have a storyboard, and a UIView property on the screen called self.blueLayer, here’s some test Objective-C code that will render out a blue square layer with a shadow.

Changing the background color to clearColor or not applying a background color at all results in no shadow.

Is there a method to have a layer without any fill and a shadow?


Thanks in advance.
Alex Zavatone


@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    

    UIColor *shadowColor;
    CGFloat alpha;
    CGFloat x;
    CGFloat y;
    CGFloat blur;
    CGFloat spread;

    

    shadowColor = [UIColor blackColor];

    

    alpha = 0.8;
    x = 0;
    y = 8.0;
    blur = 20.0;
    spread = 20.0; // 1
    
//create sublayer
    CALayer *blueLayer = [CALayer layer];
    blueLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
 //   blueLayer.frame = CGRectMake(0.0f, 0.0f, 250.0f, 128.0f);
    blueLayer.backgroundColor = [UIColor blueColor].CGColor;
    // blueLayer.backgroundColor = [UIColor clearColor].CGColor;
    // blueLayer.borderWidth = 1;
    // blueLayer.borderColor = [UIColor whiteColor].CGColor;

    // Add Shadow to layer
    //color = [UIColor greenColor];
    
    blueLayer = [self addShadowToLayerAsRect: blueLayer
                             color: shadowColor
                                 alpha: alpha
                                     x: x
                                     y: -y
                                  blur: blur
                                spread: spread];

    //add it to our view
    [self.layerView.layer addSublayer:blueLayer];
    }


- (CALayer *)addShadowToLayerAsRect:(CALayer *)layer
                    color:(UIColor *)color
                        alpha:(CGFloat)alpha
                            x:(CGFloat)x
                            y:(CGFloat)y
                         blur:(CGFloat)blur
                       spread:(CGFloat)spread
{
    
    layer.masksToBounds = NO;

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

    }
    
    return layer;
}


Steve Mills
 

On Jun 23, 2021, at 10:46, Alex Zavatone via groups.io <zav@...> wrote:

In my experiments, I noticed that if you simply create a layer for a view and attempt to add a shadow, nothing appears.

Unless some color is applied to the border or the backgroundColor of the layer, no shadow will appear.

If clearColor is used for the background, then no shadow will appear.
What about using black or white at a very low alpha, like .01%?

Steve via iPad


Alex Zavatone
 

What I’ve been doing is duplicating the layer, a task unto itself, adding the layer on top of or behind the previous layer and then getting a shadow that way. It’s not perfect but it’s currently the least bad approach I’ve been able to find.

Our graphic designers will detect a .01 shade change.

On Jun 23, 2021, at 11:39 AM, Steve Mills via groups.io <sjmills@...> wrote:

On Jun 23, 2021, at 10:46, Alex Zavatone via groups.io <zav@...> wrote:

In my experiments, I noticed that if you simply create a layer for a view and attempt to add a shadow, nothing appears.

Unless some color is applied to the border or the backgroundColor of the layer, no shadow will appear.

If clearColor is used for the background, then no shadow will appear.
What about using black or white at a very low alpha, like .01%?

Steve via iPad






Steve Mills
 

On Jun 23, 2021, at 12:42, Alex Zavatone via groups.io <zav@...> wrote:

What I’ve been doing is duplicating the layer, a task unto itself, adding the layer on top of or behind the previous layer and then getting a shadow that way. It’s not perfect but it’s currently the least bad approach I’ve been able to find.

Our graphic designers will detect a .01 shade change.


What about using black or white at a very low alpha, like .01%?
I said .01%, not 1%. I doubt the naked eye will detect that little of a change.

Steve via iPad


Alex Zavatone
 

Well, it was worth a shot. The shadow is barely visible even if I use a shadowOpacity of 1.

On Jun 23, 2021, at 6:47 PM, Steve Mills via groups.io <sjmills@...> wrote:

On Jun 23, 2021, at 12:42, Alex Zavatone via groups.io <zav@...> wrote:

What I’ve been doing is duplicating the layer, a task unto itself, adding the layer on top of or behind the previous layer and then getting a shadow that way. It’s not perfect but it’s currently the least bad approach I’ve been able to find.

Our graphic designers will detect a .01 shade change.


What about using black or white at a very low alpha, like .01%?
I said .01%, not 1%. I doubt the naked eye will detect that little of a change.

Steve via iPad






Jeremy Hughes
 

That’s what I would have expected: a transparent object produces no shadow, while a semi-transparent object produces a weak shadow.

It’s analogous to real-life objects.

Jeremy

On 24 Jun 2021, at 00:59, Alex Zavatone via groups.io <zav@...> wrote:

Well, it was worth a shot. The shadow is barely visible even if I use a shadowOpacity of 1.



On Jun 23, 2021, at 6:47 PM, Steve Mills via groups.io <sjmills@...> wrote:

On Jun 23, 2021, at 12:42, Alex Zavatone via groups.io <zav@...> wrote:

What I’ve been doing is duplicating the layer, a task unto itself, adding the layer on top of or behind the previous layer and then getting a shadow that way. It’s not perfect but it’s currently the least bad approach I’ve been able to find.

Our graphic designers will detect a .01 shade change.


What about using black or white at a very low alpha, like .01%?
I said .01%, not 1%. I doubt the naked eye will detect that little of a change.

Steve via iPad








Alex Zavatone
 

But it’s odd, since I set the shadow opacity to 1, which is 100%. Adding multiple shadows to a UIView is a royal PITA without a CGFilter since you can’t make an empty layer and apply a shadow to it. There isn’t a way that lets you tell Cocoa to “just apply this shadow at the settings I asked for at the alpha level i asked for to the rect I asked you to apply it to."

On Jun 24, 2021, at 6:08 AM, Jeremy Hughes via groups.io <moon.rabbit@...> wrote:

That’s what I would have expected: a transparent object produces no shadow, while a semi-transparent object produces a weak shadow.

It’s analogous to real-life objects.

Jeremy



On 24 Jun 2021, at 00:59, Alex Zavatone via groups.io <zav@...> wrote:

Well, it was worth a shot. The shadow is barely visible even if I use a shadowOpacity of 1.



On Jun 23, 2021, at 6:47 PM, Steve Mills via groups.io <sjmills@...> wrote:

On Jun 23, 2021, at 12:42, Alex Zavatone via groups.io <zav@...> wrote:

What I’ve been doing is duplicating the layer, a task unto itself, adding the layer on top of or behind the previous layer and then getting a shadow that way. It’s not perfect but it’s currently the least bad approach I’ve been able to find.

Our graphic designers will detect a .01 shade change.


What about using black or white at a very low alpha, like .01%?
I said .01%, not 1%. I doubt the naked eye will detect that little of a change.

Steve via iPad












Jeremy Hughes
 

On 24 Jun 2021, at 14:28, Alex Zavatone via groups.io <zav@...> wrote:

But it’s odd, since I set the shadow opacity to 1, which is 100%.
Sure — but it doesn’t matter how opaque the shadow is. An object with zero opacity won’t have a shadow (in real life or in computer graphics).

Imagine some opaque text on a transparent background (e.g. polythene in real life). The text will cast a shadow but the transparent background (polythene) won’t.

Jeremy


Alex Zavatone
 

But that’s exactly what I want. I want to add a shadow to an item with no opacity. I am specifying the shadow path as a bezier path so that I can overlay an additional shadow over a UIView.

We have a UIView. Let’s say it’s a rect. We have a need for multiple shadows on said aforementioned UIView. We would like to create a layer so that we can add a shadow to this layer and then add that very same layer to the UIView. Insert it, actually. Therefore, an empty layer would be ideal.

Right now, I am copying the layer and adding the shadow to that rect in a shadow adding method. This will suck if the shadow has partially transparent sections and the transparency of the layers add up, making those sections darker.

Simply put, you can’t add more than one shadow to a UIView. If you do, the new shadow overwrites the previous one. We have a need to add 3. This is why I’m going to these steps.

Thanks.
Alex Zavatone

On Jun 24, 2021, at 9:26 AM, Jeremy Hughes via groups.io <moon.rabbit@...> wrote:

On 24 Jun 2021, at 14:28, Alex Zavatone via groups.io <zav@...> wrote:

But it’s odd, since I set the shadow opacity to 1, which is 100%.
Sure — but it doesn’t matter how opaque the shadow is. An object with zero opacity won’t have a shadow (in real life or in computer graphics).

Imagine some opaque text on a transparent background (e.g. polythene in real life). The text will cast a shadow but the transparent background (polythene) won’t.

Jeremy