Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView with shadow, rounded corners and custom drawRect

I have to create a custom UIView that will have round corners, a border, a shadow and its drawRect() method is overridden to provide custom drawing code with which several straight lines are drawn into the view (I need to use a fast, lightweight approach here since many of these views may be rendered).

The problem I'm currently facing is that the shadow doesn't apply anymore to the round corners as soon as I override drawRect() in the view class (even without any custom code yet in it). See the attached image for the difference:

enter image description here

In the view controller I'm using the following code:

    view.layer.cornerRadius = 10;     view.layer.masksToBounds = true;      view.layer.borderColor = UIColor.grayColor().CGColor;     view.layer.borderWidth = 0.5;      view.layer.contentsScale = UIScreen.mainScreen().scale;     view.layer.shadowColor = UIColor.blackColor().CGColor;     view.layer.shadowOffset = CGSizeZero;     view.layer.shadowRadius = 5.0;     view.layer.shadowOpacity = 0.5;     view.layer.masksToBounds = false;     view.clipsToBounds = false; 

In the overridden drawContext() I would use something like:

    var context:CGContext = UIGraphicsGetCurrentContext();     CGContextSetStrokeColorWithColor(context, UIColor.redColor().CGColor);     // Draw them with a 2.0 stroke width so they are a bit more visible.     CGContextSetLineWidth(context, 2.0);     CGContextMoveToPoint(context, 0.0, 0.0); //start at this point     CGContextAddLineToPoint(context, 20.0, 20.0); //draw to this point     CGContextStrokePath(context); 

But as said above, the shadow problem occurs even without this code added.

Is there any other/better way to draw lightweight elements onto a view other than this approach that is compatible with round corners and shadows? I don't want to add any unnecessary extra views or image contexts to the view since these need to be light and performant.

like image 684
BadmintonCat Avatar asked Aug 31 '14 11:08

BadmintonCat


People also ask

How do I add inner shadow to UIView with rounded corners?

Add subview with the same color which will be centered on the parent and will be with several pixels smaller. Like this you will have space from each side of the parent. On the parent turn on clipping subviews and add shadow to the inner view. Like this, you can have an inner shadow.

How do you round UIView corners?

If you start with a regular UIView it has square corners. You can give it round corners by changing the cornerRadius property of the view's layer . and smaller values give less rounded corners. Both clipsToBounds and masksToBounds are equivalent.


1 Answers

This is a tricky one. UIView's clipsToBounds is necessary to get the rounded corners. But CALayer's masksToBounds has to be false so the shadow is visible. Somehow, everything works if drawRect is not overridden, but actually it shouldn't.

The solution is to create a superview to provide the shadow (in the demonstration below this is the shadowView). You can test the following in Playground:

class MyView : UIView {     override func drawRect(rect: CGRect) {         let c = UIGraphicsGetCurrentContext()         CGContextAddRect(c, CGRectMake(10, 10, 80, 80))         CGContextSetStrokeColorWithColor(c , UIColor.redColor().CGColor)         CGContextStrokePath(c)     } }  let superview = UIView(frame: CGRectMake(0, 0, 200, 200))  let shadowView = UIView(frame: CGRectMake(50, 50, 100, 100)) shadowView.layer.shadowColor = UIColor.blackColor().CGColor shadowView.layer.shadowOffset = CGSizeZero shadowView.layer.shadowOpacity = 0.5 shadowView.layer.shadowRadius = 5  let view = MyView(frame: shadowView.bounds) view.backgroundColor = UIColor.whiteColor() view.layer.cornerRadius = 10.0 view.layer.borderColor = UIColor.grayColor().CGColor view.layer.borderWidth = 0.5 view.clipsToBounds = true  shadowView.addSubview(view) superview.addSubview(shadowView) 

Result:

enter image description here

like image 128
Mundi Avatar answered Sep 29 '22 05:09

Mundi