What is the best way to create a shadow behind a UIImageView
Asked Answered
G

5

77

I have a UIImageView that I want to add a shadow behind. I wish that apple had that as a property but they have to make lots of things hard for us programmers so I need to ask this question.

Gibeon answered 11/1, 2010 at 19:51 Comment(2)
Likely, you want to use Core Graphics drawing functions to draw the shadow.Relume
These questions are very similar to yours: https://mcmap.net/q/266382/-uiimage-shadow-trouble, #1943587Fifine
L
219

There's a better and easier way to do this. UIImageView inherits from UIView so it has a layer property. You can access the layer's shadow properties and bam, you got a shadow.

If you have the UIImageView as an IBOutlet to a nib file, you can just implement the awakeFromNib e.g.

Objective-C

- (void)awakeFromNib {
    imageView.layer.shadowColor = [UIColor purpleColor].CGColor;
    imageView.layer.shadowOffset = CGSizeMake(0, 1);
    imageView.layer.shadowOpacity = 1;
    imageView.layer.shadowRadius = 1.0;
    imageView.clipsToBounds = NO;
}

Don't forget to #import "QuartzCore/CALayer.h"


For Swift, you can go about it multiple ways. Create a class extension, subclass, or an imageView instance. Whichever the way, the process is the same in modifying the layers shadow property.

Swift 3

override func awakeFromNib() {
    super.awakeFromNib()

    imageView.layer.shadowColor = UIColor.purple.cgColor
    imageView.layer.shadowOffset = CGSize(width: 0, height: 1)
    imageView.layer.shadowOpacity = 1
    imageView.layer.shadowRadius = 1.0
    imageView.clipsToBounds = false
}
Ladner answered 1/10, 2010 at 23:14 Comment(6)
You also may need imageView.clipsToBounds = NO; or the shadow will be clipped away.Treiber
you will also need to #import "QuartzCore/CALayer.h"Playacting
@MaxHowell using clipsToBounds added the shadow, but now my image overflow's its bounds as well when using mode "Aspect Fill". Is there a way to clip the image but not the shadow?Armelda
@DerekDahmer you will have to add the imageView as a subview of another view that you then apply the shadow, and then clip the imageView but not the container view. I have found no other way to handle this sort of thing.Treiber
Add imageView.layer.shouldRasterize = YES; to speed up processingHalliehallman
Wow, rasterization helps a lot if you animate your imageView. If you use it, you should also add this: imageView.layer.rasterizationScale = image.scale; to be compatible with retina images.Snakebird
L
11

The simplest thing to do is add a shadow layer to your image view:

CALayer             *layer = [CALayer layer];
CGRect              bounds = self.bounds;

layer.bounds = bounds;
layer.position = CGPointMake(bounds.size.width / 2 + 3, bounds.size.height / 2 + 3);
layer.backgroundColor = [UIColor colorWithWhite: 0.25 alpha: 0.55].CGColor;
layer.zPosition = -5;

[self.layer addSublayer: layer];

Be sure "Clip Subviews" is turned off for the view

Leopard answered 11/1, 2010 at 20:2 Comment(4)
why are you making a CGRect *bounds when you can just set the layer's bounds to self.bounds? And where does the shadow come into place?Gibeon
I create a temp variable for readability; typing out self.bounds is a little longer than just bounds, and makes the code a little less readable. This layer IS the shadow. Of course, this presupposes you've got a square image; if you're doing a non-rectangular image, you'll have to use a custom image mask.Leopard
Well I want to have it faded and I don't know how I would do that. Pleas help!Gibeon
Fading is a separate task entirely. If you want to have a custom shadow (something other than a simple dark rectangle behind your image), you should take the image, make it into a mask (ie, all black and transparent), apply your fade, and then draw it behind the original, using either Quartz, or sticking into a layer.Leopard
A
10

Swift solution with extension. Subclassing is not required. Call myImage.addShadow() from viewDidLoad(). This should work for UIView and UIImageView.

extension UIView {

    func addShadow() {
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.shadowOpacity = 0.5
        layer.shadowRadius = 5
        clipsToBounds = false
    }
}
Armure answered 10/2, 2017 at 13:36 Comment(1)
When I try to call this I get 'Value of type 'UIImage' has no member 'addShadow'Commissure
G
5

in additional to that, if you want to make white border and shadow you can use that code :

//shadow part
imageView.layer.shadowColor = [UIColor blackColor].CGColor;
imageView.layer.shadowOffset = CGSizeMake(0, 1);
imageView.layer.shadowOpacity = 1;
imageView.layer.shadowRadius = 1.0;
//white border part
[imageView.layer setBorderColor: [[UIColor whiteColor] CGColor]];
[imageView.layer setBorderWidth: 2.0];
Ginglymus answered 9/5, 2012 at 13:59 Comment(2)
But in this case, how do you make the shadow part of the .image property, to let's say, save or show that image somewhere else?Anglicist
You can't. You aren't editing the image, you are adorning it for display. To actually edit the bitmap data is much more complicated. Consider simply adorning the image everywhere you display it as you generally do not want to process images to add these sort of effects unless you do so in a back end that processes them in batches.Directions
L
0

Swift 5.x

profileImageView.layer.cornerRadius = profileImageView.frame.size.width/2
profileImageView.clipsToBounds = false
profileImageView.layer.shadowColor = UIColor.black.cgColor
profileImageView.layer.shadowOpacity = 0.7
profileImageView.layer.shadowOffset =  CGSize(width: 2, height: 2)
profileImageView.layer.shadowRadius = 10
Lin answered 8/2, 2021 at 15:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.