How to Round a Shadow in iOS

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)
}

Creating a shadow for a UIImageView that has rounded corners?

If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. In order to resolve this, you can create two views. The container view should have the shadow, and its subview should have the rounded corners.

The container view has clipsToBounds set to false, and has the shadow properties applied. If you want the shadow to be rounded as well, use the UIBezierPath constructor that takes in a roundedRect and cornerRadius.

let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
outerView.clipsToBounds = false
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOpacity = 1
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowRadius = 10
outerView.layer.shadowPath = UIBezierPath(roundedRect: outerView.bounds, cornerRadius: 10).cgPath

Next, set the image view (or any other type of UIView) to be the same size of the container view, set clipsToBounds to true, and give it a cornerRadius.

let myImage = UIImageView(frame: outerView.bounds)
myImage.clipsToBounds = true
myImage.layer.cornerRadius = 10

Finally, remember to make the image view a subview of the container view.

outerView.addSubview(myImage)

The result should look something like this:

Sample Image

rounded edges with a shadow

Add dummy container view and assign it the shadow, after that put inside of it the image view like this:
Declare your objects under your class controller:

let imgV = UIImageView()
let dummyView = UIView()

after that in viewdidLoad set property and constraints:

imgV.image = UIImage(named: "yourImage")
imgV.contentMode = .scaleToFill
imgV.layer.cornerRadius = 20
imgV.clipsToBounds = true
imgV.translatesAutoresizingMaskIntoConstraints = false

dummyView.center = self.view.center
dummyView.backgroundColor = UIColor.yellow
dummyView.layer.shadowColor = UIColor.gray.cgColor
dummyView.layer.shadowOpacity = 1
dummyView.layer.shadowOffset = CGSize(width: 2, height: 2)
dummyView.layer.shadowRadius = 5
dummyView.layer.cornerRadius = 20
dummyView.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(dummyView)
dummyView.heightAnchor.constraint(equalToConstant: 200).isActive = true
dummyView.widthAnchor.constraint(equalToConstant: 200).isActive = true
dummyView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
dummyView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

dummyView.addSubview(imgV)
imgV.topAnchor.constraint(equalTo: dummyView.topAnchor).isActive = true
imgV.bottomAnchor.constraint(equalTo: dummyView.bottomAnchor).isActive = true
imgV.leadingAnchor.constraint(equalTo: dummyView.leadingAnchor).isActive = true
imgV.trailingAnchor.constraint(equalTo: dummyView.trailingAnchor).isActive = true

this is the result

Sample Image

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

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


Related Topics



Leave a reply



Submit