Apply a Shadow on a Uiview That Have Same Corner Radius Than View

UIView with rounded corners and drop shadow?

The following code snippet adds a border, border radius, and drop shadow to v, a UIView:

// border radius
[v.layer setCornerRadius:30.0f];

// border
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];

// drop shadow
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];

Swift 5 Version :

// border radius
v.layer.cornerRadius = 30.0

// border
v.layer.borderColor = UIColor.lightGray.cgColor
v.layer.borderWidth = 1.5

// drop shadow
v.layer.shadowColor = UIColor.black.cgColor
v.layer.shadowOpacity = 0.8
v.layer.shadowRadius = 3.0
v.layer.shadowOffset = CGSize(width: 2.0, height: 2.0)

You can adjust the settings to suit your needs.

Also, add the QuartzCore framework to your project and:

#import <QuartzCore/QuartzCore.h>

See my other answer regarding masksToBounds.


Note

This may not work in all cases. If you find that this method interferes with other drawing operations that you are performing, please see this answer.

How to round top two corners of UIView and add shadow above?

SWIFT 5: iOS 11 introduced maskedCorners which results in smoother and better quality results. You can still use the UIRectCorner in the function call and have it translated to CACornerMask:

extension UIView {

func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
if #available(iOS 11.0, *) {
clipsToBounds = true
layer.cornerRadius = radius
layer.maskedCorners = CACornerMask(rawValue: corners.rawValue)
} else {
let path = UIBezierPath(
roundedRect: bounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius)
)
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}

func addShadow(shadowColor: CGColor = UIColor.label.cgColor,
shadowOffset: CGSize = CGSize(width: 1.0, height: 2.0),
shadowOpacity: Float = 0.4,
shadowRadius: CGFloat = 3.0) {
self.layer.shadowColor = shadowColor
self.layer.shadowOffset = shadowOffset
self.layer.shadowOpacity = shadowOpacity
self.layer.shadowRadius = shadowRadius
self.layer.masksToBounds = false
}
}

These functions need to be applied in layoutSubviews() of your superview.

override func layoutSubviews() {
roundCorners([.topLeft, .topRight], radius: 15)
addShadow(shadowColor: UIColor.text1.cgColor, shadowOffset: CGSize(width: 0, height: -3), shadowOpacity: 0.2, shadowRadius: 5)
}

How to add inner shadow to UIView with rounded corners

It's a trick. You give shadow and border to same view, the shadow will fall inside the view. please make sure the background color of view is clear. use the below code for reference.

yourView.layer.shadowColor = UIColor.gray.cgColor
yourView.layer.shadowOpacity = 0.3
yourView.layer.shadowOffset = CGSize.zero
yourView.layer.shadowRadius = 6
yourView.layer.masksToBounds = true
yourView.layer.borderWidth = 1.5
yourView.layer.borderColor = UIColor.white.cgColor
yourView.layer.cornerRadius = imageView.bounds.width / 2

Swift - Problems with corner radius and drop shadow

The following Swift 5 / iOS 12 code shows how to set a subclass of UIButton that allows to create instances with rounded corners and shadow around it:

import UIKit

final class CustomButton: UIButton {

private var shadowLayer: CAShapeLayer!

override func layoutSubviews() {
super.layoutSubviews()

if shadowLayer == nil {
shadowLayer = CAShapeLayer()
shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 12).cgPath
shadowLayer.fillColor = UIColor.white.cgColor

shadowLayer.shadowColor = UIColor.darkGray.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowOffset = CGSize(width: 2.0, height: 2.0)
shadowLayer.shadowOpacity = 0.8
shadowLayer.shadowRadius = 2

layer.insertSublayer(shadowLayer, at: 0)
//layer.insertSublayer(shadowLayer, below: nil) // also works
}
}

}

According to your needs, you may add a UIButton in your Storyboard and set its class to CustomButton or you may create an instance of CustomButton programmatically. The following UIViewController implementation shows how to create and use a CustomButton instance programmatically:

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let button = CustomButton(type: .system)
button.setTitle("Button", for: .normal)
view.addSubview(button)

button.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
let widthConstraint = button.widthAnchor.constraint(equalToConstant: 100)
let heightConstraint = button.heightAnchor.constraint(equalToConstant: 100)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}

}

The previous code produces the image below in the iPhone simulator:

Sample Image

UIView with shadow, rounded corners and custom drawRect

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:

Sample Image



Related Topics



Leave a reply



Submit