cell.layer.shadowOpacity = 1.0;
cell.layer.shadowRadius = 5;
cell.layer.shadowColor = [UIColor blackColor].CGColor;
cell.layer.shadowOffset = CGSizeMake(0.0, -2.0);
cell.layer.shadowPath = [UIBezierPath bezierPathWithRect:cell.layer.bounds].CGPath;
I have been trying to get a shadow to appear around my cells, however I haven't had any luck. I've even tried ordering the zPosition of my cells to see if it works, and nothing. What am I missing?
I want to be able to draw my shadows so the cell with index.row = x appears to be above the cell with index.row = x-1
You might get this to work to some extent by setting the layer's masksToBounds to NO. But don't. Don't do any of what you're doing. What you're trying to do is a really bad idea, because you are forcing the render tree to constantly rerender the shadow while the table scrolls, which will cause a low frame rate and stuttering of the scroll.
Related
I'm creating table view with custom cells, which looks like news feed - on gray background there are rectangles with rounded corners and shadow.
While cellForRowAtIndexPath method is calling I'm setting shadow like this:
cell.postCard.layer.cornerRadius = 3
cell.postCard.layer.shadowColor = UIColor.darkGrayColor().CGColor
cell.postCard.layer.shadowOffset = CGSizeMake(0,1)
cell.postCard.layer.shadowRadius = 3
cell.postCard.layer.shadowOpacity = 0.5
cell.layer.shadowPath = UIBezierPath(rect: cell.postCard.layer.bounds).CGPath
Where postCard is UIView - it's container for all context of cell.
I've read that I need to add shadowPath to get good performance but I think it's not working because when I'm slowly moving table view is stuttering. Can be reason of using simulator than real device?
You are setting shadow path to cell's layer, while modifying shadow settings for cell.postCard
cell.postCard.layer.shadowOpacity = 0.5
cell.layer.shadowPath = UIBezierPath(rect: cell.postCard.layer.bounds).CGPath
Is this really what you need?
Also, you should set 'cell.clipsToBounds = false' for your cell.
Try to read about the shouldRasterize and how it is working with shadows and corner radius of the UI elements. You can boost performance by manipulation of the shouldRasterize value.
I have a UIScrollView that pretty much functions like a Facebook news feed. I thought my elements were slowing the scroll fps down. By process of elimination, I found out that the shadows slow down my app.
The UIView boxes inside the scroll view have such configuration:
self.layer.shadowColor = UIColor.blackColor().CGColor
self.layer.shadowOffset = CGSizeMake(0, 2)
self.layer.shadowRadius = 2
self.layer.shadowOpacity = 0.15
Like a news feed, my scroll view has many boxes, therefore having UIViews with their own shadows. How do I go with this without slowing down my app?
There's a bunch of stuff on speeding up UIScrollViews:
CALayer - Shadow causes a performance hit?
https://markpospesel.wordpress.com/2012/04/03/on-the-importance-of-setting-shadowpath/
If you use custom CALayer instances -- especially with shadows -- stuff that requires processing power, you should use
scrollView.layer.shouldRasterize = YES;
scrollView.layer.rasterizationScale = [UIScreen mainScreen].scale;
Also a shadowPath could speed up your scrollview as well something like this:
[scrollView.layer setShadowPath:[[UIBezierPath bezierPathWithRect:myView.bounds] CGPath]];
Setting a shadowPath allows iOS to not recalculate how it should draw the shadow every time it draws the view, thus improving performance.
In swift, something like this:
let shadowPath = UIBezierPath(rect: view.bounds);
view.layer.masksToBounds = false;
view.layer.shadowColor = UIColor.blackColor().CGColor;
view.layer.shadowOffset = CGSizeMake(0, 0.5);
view.layer.shadowOpacity = 0.2;
view.layer.shadowPath = shadowPath.CGPath;
Setting the shadowPath will improve performance and look the same so long as your views are opaque. You could just set it to the bounds of the view or layer like so:
CGPathRef shadowPath = CGPathCreateWithRect(self.bounds, NULL);
self.layer.shadowPath = shadowPath;
CGPathRelease(shadowPath);
In Swift:
layer.shadowPath = CGPathCreateWithRect(bounds, nil)
The memory management is handled for you (discussed here).
I'm trying to see if there's a way to create a UIView with a shadow behavior compliant with material design. My understanding is that the shadow gets more intense as the object is further removed from the background surface.
I can manually add a shadow like this, however this shadow does not calculate how intense the shadow should be (based on Z order).
button.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:button.layer.bounds cornerRadius:11].CGPath;
button.layer.shadowOpacity = 1.0;
button.layer.shadowOffset = CGSizeMake(1,1);
button.layer.shadowColor = [UIColor blackColor].CGColor;
How do I create a UIView which will behave like Google's material design? I found this example, called Material Kit, however it simply hides shadow on touch
One way in which Google does this is by emphasizing the use of a
‘z-axis’ to create a sense of depth in which elements can occupy
different levels. In order to show that an element is occupying a
higher level on the z-axis, shadows are used around its border, being
cast on to the level below. What this creates is the illusion of an
interactive layer/element that exists above a different, lower
interactive layer/element.
You could subclass UIButton, and first set the shadow properties to your liking:
button.layer.shadowOffset = CGSizeMake(0, 1);
button.layer.shadowRadius = 5;
button.layer.shadowOpacity = 0;
Then change the shadowOpacity property when the highlighted state changes:
- (void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
self.layer.shadowOpacity = (highlighted ? 0.85 : 0);
}
In order to apply both a shadow and a rounded corner, you need to use 2 nested views. This is because the two effects require competing masksToBounds properties.
Nest 2 UIViews. Apply the shadow to the outer view, setting masksToBounds = false. Then apply the rounded corner to the inner view, which requires masksToBounds = true.
Note that, according to Apple docs, masksToBounds is equivalent to clipsToBounds.
Does any one know how to achieve the shadow effect with no gradient? Like the screenshot show below
Another concern is the sequence of subviews, i.e the view in front may hide the effect of the view in behind. How to overcome this?
For the first problem you can change the shadowRadius of the shadow, for example:
//You must include QuartzCore framework (#import <QuartzCore/QuartzCore.h>)
view.layer.cornerRadius = 5;
view.layer.shadowRadius = 0; //The shadow should be rendered as a solid shape
view.layer.shadowOffset = CGSizeMake(0, 2);
view.layer.shadowOpacity = 0.5;
view.layer.shadowColor = [UIColor blackColor].CGColor;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:view.bounds];
view.layer.shadowPath = path.CGPath; //This is very important!
Remember to always set the shadowPath! If you don't the performance of rendering the shadow will decrease a lot.
For the second problem, sorry but I don't think there's a way to let the shadow of an object appear over another view that is over the original one.
I know there have been many questions on this before however none seem to work in my scenario. Pretty much I am trying to make the top maybe 10 points below the top of the frame of my tableview somewhat darker so have a nicer effect than just the cells scrolling off the frame.
Pretty much I need to accomplish an effect where the alpha starts at 0 and ends at 1 of a gray color which is 10 points high. This way there is some sort of subtle area before the top of the frame so that it doesn't look like the cells are just moving out of the frame.
Is this possible?
Thanks!
You can set a shadow to the navigationBar layer, assuming you are using one.
self.navigationController.navigationBar.layer.shadowColor = [[UIColor blackColor] CGColor];
self.navigationController.navigationBar.layer.shadowOffset = CGSizeMake(0.0f,0.0f);
self.navigationController.navigationBar.layer.shadowOpacity = 1.0f;
self.navigationController.navigationBar.layer.shadowRadius = 4.0f;
If you are not using a navigation controller, then you can apply this same type of shadow to a UIView's layer.