Inner shadow effect on UIView layer?

Discover The Secrets Of Drawing Realistic Pencil Portraits WITHOUT Wasting Your Precious Time Going Through Years Of Trials And Errors! Get it now!

For anyone else wondering how to draw an inner shadow using Core Graphics as per Costique suggestion, then this is how: (on iOS adjust as needed) In your drawRect: method CGRect bounds = self bounds; CGContextRef context = UIGraphicsGetCurrentContext(); CGFloat outsideOffset = 40. F; // this value doesn't really matter - just > 0 CGFloat radius = 0.5f * CGRectGetHeight(bounds); // Create the "visible" path, which will be the shape that gets the inner shadow // In this case it's just a rounded rect, but could be as complex as your want CGMutablePathRef visiblePath = CGPathCreateMutable(); CGPathMoveToPoint(visiblePath, NULL, bounds.size. Width-radius, bounds.size.

Height); CGPathAddArc(visiblePath, NULL, bounds.size. Width-radius, radius, radius, 0.5f*M_PI, 1.5f*M_PI, YES); CGPathAddLineToPoint(visiblePath, NULL, radius, 0. F); CGPathAddArc(visiblePath, NULL, radius, radius, radius, 1.5f*M_PI, 0.5f*M_PI, YES); CGPathAddLineToPoint(visiblePath, NULL, bounds.size.

Width-radius, bounds.size. Height); CGPathCloseSubpath(visiblePath); // Fill this path UIColor *aColor = UIColor redColor; aColor setFill; CGContextAddPath(context, visiblePath); CGContextFillPath(context); // Now create a larger rectangle, which we're going to subtract the visible path from // and apply a shadow CGMutablePathRef path = CGPathCreateMutable(); // Draw a big rectange CGPathMoveToPoint(path, NULL, -outsideOffset, -outsideOffset); CGPathAddLineToPoint(path, NULL, bounds.size. Width+outsideOffset, -outsideOffset); CGPathAddLineToPoint(path, NULL, bounds.size.

Width+outsideOffset, bounds.size. Height+outsideOffset); CGPathAddLineToPoint(path, NULL, -outsideOffset, bounds.size. Height+outsideOffset); // Add the visible path (so that it gets subtracted for the shadow) CGPathAddPath(path, NULL, visiblePath); CGPathCloseSubpath(path); // Add the visible paths as the clipping path to the context CGContextAddPath(context, visiblePath); CGContextClip(context); // Now setup the shadow properties on the context aColor = UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f; CGContextSaveGState(context); CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 3.0f, aColor CGColor); // Now fill the rectangle, so the shadow gets drawn aColor = UIColor colorWithWhite:1.

F alpha:1. F; aColor setFill; CGContextSaveGState(context); CGContextAddPath(context, path); CGContextFillPath(context); // Release the paths CGPathRelease(path); CGPathRelease(visiblePath) So, essentially there are the following steps: Create your path Set the fill color you want, add this path to the context, and fill the context Now create a larger rectangle that can bound the visible path. Before closing this path, add the visible path.

Then close the path, so that you create a shape with the visible path subtracted from it. You might want to investigate the fill methods (non-zero winding of even/odd) depending on how you created these paths. In essence, to get the subpaths to "subtract" when you add them together, you need to draw them (or rather construct them) in opposite directions, one clockwise and the other anti-clockwise Then you need to set your visible path as the clipping path on the context, so that you don't draw anything outside it to the screen Then setup up the shadow on the context, which includes the offset, blur and color Then fill the big shape with the hole in it.

The color doesn't matter, because if you've done everything right, you won't see this color, just the shadow.

For anyone else wondering how to draw an inner shadow using Core Graphics as per Costique suggestion, then this is how: (on iOS adjust as needed) In your drawRect: method... CGRect bounds = self bounds; CGContextRef context = UIGraphicsGetCurrentContext(); CGFloat outsideOffset = 40. F; // this value doesn't really matter - just > 0 CGFloat radius = 0.5f * CGRectGetHeight(bounds); // Create the "visible" path, which will be the shape that gets the inner shadow // In this case it's just a rounded rect, but could be as complex as your want CGMutablePathRef visiblePath = CGPathCreateMutable(); CGPathMoveToPoint(visiblePath, NULL, bounds.size. Width-radius, bounds.size.

Height); CGPathAddArc(visiblePath, NULL, bounds.size. Width-radius, radius, radius, 0.5f*M_PI, 1.5f*M_PI, YES); CGPathAddLineToPoint(visiblePath, NULL, radius, 0. F); CGPathAddArc(visiblePath, NULL, radius, radius, radius, 1.5f*M_PI, 0.5f*M_PI, YES); CGPathAddLineToPoint(visiblePath, NULL, bounds.size.

Width-radius, bounds.size. Height); CGPathCloseSubpath(visiblePath); // Fill this path UIColor *aColor = UIColor redColor; aColor setFill; CGContextAddPath(context, visiblePath); CGContextFillPath(context); // Now create a larger rectangle, which we're going to subtract the visible path from // and apply a shadow CGMutablePathRef path = CGPathCreateMutable(); // Draw a big rectange CGPathMoveToPoint(path, NULL, -outsideOffset, -outsideOffset); CGPathAddLineToPoint(path, NULL, bounds.size. Width+outsideOffset, -outsideOffset); CGPathAddLineToPoint(path, NULL, bounds.size.

Width+outsideOffset, bounds.size. Height+outsideOffset); CGPathAddLineToPoint(path, NULL, -outsideOffset, bounds.size. Height+outsideOffset); // Add the visible path (so that it gets subtracted for the shadow) CGPathAddPath(path, NULL, visiblePath); CGPathCloseSubpath(path); // Add the visible paths as the clipping path to the context CGContextAddPath(context, visiblePath); CGContextClip(context); // Now setup the shadow properties on the context aColor = UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f; CGContextSaveGState(context); CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 3.0f, aColor CGColor); // Now fill the rectangle, so the shadow gets drawn aColor = UIColor colorWithWhite:1.

F alpha:1. F; aColor setFill; CGContextSaveGState(context); CGContextAddPath(context, path); CGContextFillPath(context); // Release the paths CGPathRelease(path); CGPathRelease(visiblePath); So, essentially there are the following steps: Create your path Set the fill color you want, add this path to the context, and fill the context Now create a larger rectangle that can bound the visible path. Before closing this path, add the visible path.

Then close the path, so that you create a shape with the visible path subtracted from it. You might want to investigate the fill methods (non-zero winding of even/odd) depending on how you created these paths. In essence, to get the subpaths to "subtract" when you add them together, you need to draw them (or rather construct them) in opposite directions, one clockwise and the other anti-clockwise.

Then you need to set your visible path as the clipping path on the context, so that you don't draw anything outside it to the screen. Then setup up the shadow on the context, which includes the offset, blur and color. Then fill the big shape with the hole in it.

The color doesn't matter, because if you've done everything right, you won't see this color, just the shadow.

It's currently based on the bounds, but I'd like to based on a set radius instead (like 5.0f). With the above code, it's rounded way too much. – runmad Oct 20 at 23:49 1 @runmad Well, you can create any sort of visible CGPath that you want, the example used here is just that, an example, chosen for brevity.

If you'd like to create a rounded rect, then you can just do something like: CGPath visiblePath = UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius. CGPath Hope that helps. – Daniel Thorpe Oct 21 at 9:49.

It is possible to draw an inner shadow with Core Graphics by making a large rectangle path outside the bounds, subtracting a bounds-sized rectangle path and filling the resulting path with a "normal" shadow on. However, since you need to combine it with a gradient layer, I think an easier solution is to create a 9-part transparent PNG image of the inner shadow and stretch it to the right size. The 9-part shadow image would look like this (its size is 21x21 pixels): CALayer *innerShadowLayer = CALayer layer; innerShadowLayer.

Contents = (id)UIImage imageNamed: @"innershadow. Png". CGImage; innerShadowLayer.

ContentsCenter = CGRectMake(10.0f/21.0f, 10.0f/21.0f, 1.0f/21.0f, 1.0f/21.0f); Then set innerShadowLayer's frame and it should stretch the shadow properly.

Yeah, I suppose you're right. Just wanted the layer to be as flat as possible. I could create the image in Photoshop with the inner shadow and gradient look, I just have issues with the colours matching up 100% on the device when using an image.

– runmad Dec 13 '10 at 17:45 Yep, that's an issue with all gradients and shadows, I just cannot reproduce these Photoshop effects 1:1 on iOS, hard as I try. – Costique Dec 13 '10 at 17:51.

Bit of a round-about way, but it avoids having to use images (read: easy to change colors, shadow radius, etc. ) and it's only a few lines of code. Add a UIImageView as the first subview of the UIView you want the dropshadow on. I use IB, but you can do the same programmatically.

Assuming the reference to the UIImageView is 'innerShadow' ` innerShadow layer setMasksToBounds:YES; innerShadow layer setCornerRadius:12.0f; innerShadow layer setBorderColor:UIColorFromRGB(180, 180, 180) CGColor; innerShadow layer setBorderWidth:1.0f; innerShadow layer setShadowColor:UIColorFromRGB(0, 0, 0) CGColor; innerShadow layer setShadowOffset:CGSizeMake(0, 0); innerShadow layer setShadowOpacity:1; innerShadow layer setShadowRadius:2.0; Caveat: You have to have a border, or else the shadow doesn't show up. UIColor clearColor doesn't work.In the example I use a different color, but you can mess with it to get it to have the same color as the beginning of the shadow. :).

I left it out but assume you'd do this as part of adding the imageview - make sure to set the frame to the same rect as the parent UIView. If you're using IB, set struts and springs right to have the shadow size with the view if you'll be changing the parent view's frame. In code there should be a resize mask you can OR to do the same, AFAIK.

– jinglesthula Jun 10 at 17:49 This is the easiest way now, but be aware that the CALayer shadow methods are only available in iOS 3.2 and later. I support 3.1, so I surround setting these attributes in an if (layer respondsToSelector:@selector(setShadowColor:)) { – DougW Jul 12 at 19:54 This doesn't seem to work for me. At least on xcode 4.2 and ios simulator URL1 make the shadow appear I have to add a background color... at which point the dropshadow appears only outside.

– Andrea Jul 17 at 15:36 @Andrea - bear in mind the caveat I mentioned above. I think a background color or a border might have the same effect of 'giving it something to add the shadow to'. As for it appearing outside, if the UIImageView isn't a subview of the one you want the inner shadow on that might be it - I'd have to look at your code to see.

– jinglesthula Jul 18 at 22:57 Just to rectify my previous statement... the code actually works... I was missing something but unfortunately I can't remember it right now. :) So... thanks for sharing this code snippet. – Andrea Aug 19 at 14:07.

I'm not too sure how you could do this in xcode, but if you have access to Photoshop, you can create an image that has an inner shadow effect. Then in interface builder, add it to a UIImageView and then put your UIView on top of it. There is probably another way to do it though.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions