17

I am trying to display a UIView with round corners and with a drop shadow. But the problem is that maskToBounds property only works for either of the case.

If maskToBounds is YES then round corners show up and when NO then shadow shows up. Here is the implementation but it only displays round corners with no shadow:

[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_gradient.jpeg"]]];


    self.view.layer.masksToBounds = YES; 
    self.view.layer.opaque = NO; 
    self.view.layer.cornerRadius = 15.0f; 


    self.view.layer.shadowColor = [UIColor blackColor].CGColor;
    self.view.layer.shadowRadius = 5.0; 
    self.view.layer.shadowOffset = CGSizeMake(3.0, 3.0);
    self.view.layer.shadowOpacity = 0.9f;

ideas!

NOTE: I have read and implemented the code in the following thread but it does not work: UIView with rounded corners and drop shadow?

UPDATE 1:

I tried to create two separate views. One will represent the radius and one will represent the shadow. The problem is that is creates the shadow on top of the radius view as shown in the screenshot below:

enter image description here

H

ere is the code: 

 self.view.layer.masksToBounds = YES; 
    self.view.layer.opaque = NO; 
    self.view.layer.cornerRadius = 15.0f; 
   // self.view.backgroundColor = [UIColor clearColor];
    self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_gradient.jpeg"]];
//
    UIView *shadowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
    shadowView.layer.shadowRadius = 2.0; 
    shadowView.backgroundColor = [UIColor clearColor];
    shadowView.layer.shadowOffset = CGSizeMake(3.0, 3.0);
    shadowView.layer.shadowOpacity = 0.9f;
    shadowView.layer.shadowPath = [UIBezierPath 
                                                                   bezierPathWithRect:CGRectMake(0, 0, 100, 100)].CGPath;

    [self.view addSubview:shadowView];

UPDATE 2:

Inverted still does not work. No round corners are created.

UIView *roundCornerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    roundCornerView.layer.masksToBounds = YES; 
    roundCornerView.layer.opaque = NO; 
    roundCornerView.layer.cornerRadius = 15.0f; 

    self.view.layer.shadowColor = [UIColor blackColor].CGColor;
    self.view.layer.shadowRadius = 2.0; 
    //self.view.backgroundColor = [UIColor clearColor];
    self.view.layer.shadowOffset = CGSizeMake(3.0, 3.0);
    self.view.layer.shadowOpacity = 0.9f;
    self.view.layer.shadowPath = [UIBezierPath 
                                                                   bezierPathWithRect:CGRectMake(0, 0, 100, 100)].CGPath;

    [self.view addSubview:roundCornerView];

SOLUTION:

 UIView *roundCornerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    roundCornerView.layer.masksToBounds = YES; 
    roundCornerView.layer.opaque = NO; 
    roundCornerView.layer.cornerRadius = 15.0f; 

    roundCornerView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_gradient.jpeg"]];

    self.view.layer.shadowColor = [UIColor blackColor].CGColor;
    self.view.layer.shadowRadius = 2.0; 
    self.view.backgroundColor = [UIColor clearColor];
    self.view.layer.shadowOffset = CGSizeMake(3.0, 3.0);
    self.view.layer.shadowOpacity = 0.9f;
    //self.view.layer.shadowPath = [UIBezierPath 
      //                                                             bezierPathWithRect:CGRectMake(0, 0, 100, 100)].CGPath;

    [self.view addSubview:roundCornerView];
Community
  • 1
  • 1
azamsharp
  • 19,710
  • 36
  • 144
  • 222
  • possible duplicate of [UIView with rounded corners and drop shadow?](http://stackoverflow.com/questions/4754392/uiview-with-rounded-corners-and-drop-shadow) – Evan Mulawski Jul 11 '12 at 17:06
  • 1
    Nope! Already checked out that question and tried that approach and it did not work. – azamsharp Jul 11 '12 at 17:07
  • Here is a hackish idea you could try to set the border width to something like 20 with a UIColor clearColor – Nate Flink Jul 11 '12 at 17:17
  • Clear color will not work since it will display the map beneath the uiview. – azamsharp Jul 11 '12 at 17:29
  • The subview approach is no longer necessary in iOS 11, which has a new CALayer property specifically to mask corners: https://stackoverflow.com/a/49559042/7450 – jlew Mar 29 '18 at 14:47

3 Answers3

11

Create two views. one with the drop shadow (and don't forget to set the shadowPath) in which you add a subview with cornerRadius and maskToBounds.

itsji10dra
  • 4,603
  • 3
  • 39
  • 59
iSofTom
  • 1,718
  • 11
  • 15
  • You have to invert the two views, cliped view have to be a subview of shadowView. – iSofTom Jul 11 '12 at 17:32
  • In fact there is corners but you can't see theme for two reasons. First because there is no content in you clipped view, second because the shadow's path is a rect and not a rounded rect! – iSofTom Jul 11 '12 at 18:59
10

The accepted answer didn't include any code, so here is an example in Swift (See the original question for the OP's solution in Obj-C).

enter image description here

Like the accepted answer, this solution uses separate views for the shadow and the corner radius.

// add the shadow to the base view
baseView.backgroundColor = UIColor.clear
baseView.layer.shadowColor = UIColor.black.cgColor
baseView.layer.shadowOffset = CGSize(width: 3, height: 3)
baseView.layer.shadowOpacity = 0.7
baseView.layer.shadowRadius = 4.0

// improve performance
baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale

// add the border to subview
let borderView = UIView()
borderView.frame = baseView.bounds
borderView.layer.cornerRadius = 10
borderView.layer.borderColor = UIColor.black.cgColor
borderView.layer.borderWidth = 1.0
borderView.layer.masksToBounds = true
baseView.addSubview(borderView)

// add any other subcontent that you want clipped
let otherSubContent = UIImageView()
otherSubContent.image = UIImage(named: "lion")
otherSubContent.frame = borderView.bounds
borderView.addSubview(otherSubContent)

My full answer is here.

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • How to do it if view is added in Storyboard ?, Do I need to take 3 Views ? or it is not possible ? – Prashant Tukadiya May 17 '17 at 13:12
  • @MikeAlter, I haven't done it in the storyboard, though I think it would be possible using three views. Take a look at using [User Defined Runtime Attributes](http://stackoverflow.com/a/22396838/3681880) if the necessary attributes are not available in the attribute inspector. – Suragch May 17 '17 at 13:45
1

You can do it with a single view by applying following:

1. Firstly add a corner radius

yourview.layer.cornerRadius = 5.0

2. Call a function below

shadowToView(view : yourview)


func shadowToView(view : UIView){
    view.layer.shadowOffset = CGSize(width: 0, height: 3)
    view.layer.shadowOpacity = 0.6
    view.layer.shadowRadius = 3.0
    view.layer.shadowColor = UIColor.darkGray.cgColor
}
iElden
  • 1,272
  • 1
  • 13
  • 26