Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save PhanithNY/8162af3ad0c0907632369751ea58ac19 to your computer and use it in GitHub Desktop.
Save PhanithNY/8162af3ad0c0907632369751ea58ac19 to your computer and use it in GitHub Desktop.
A view that combines shadow, corner radius, and translucent background into one view
class ShadowCutoutView: UIView {
var contentView: UIView? {
didSet {
oldValue?.removeFromSuperview()
guard let contentView else {
return
}
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(contentView)
}
}
let shadowLayer = CALayer()
private let shadowMaskLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
shadowLayer.mask = shadowMaskLayer
layer.addSublayer(shadowLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
let shadowCornerRadius = contentView?.layer.cornerRadius ?? 0
let shadowPadding = shadowLayer.shadowRadius * 4
shadowLayer.frame = bounds
shadowLayer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: shadowCornerRadius).cgPath
let maskFrame = CGRect(
x: -shadowPadding,
y: -shadowPadding,
width: bounds.width + shadowPadding * 2,
height: bounds.height + shadowPadding * 2
)
let maskPath = UIBezierPath(rect: CGRect(origin: .zero, size: maskFrame.size))
let cutoutPath = UIBezierPath(
roundedRect: bounds.offsetBy(dx: shadowPadding, dy: shadowPadding),
cornerRadius: shadowCornerRadius
)
maskPath.append(cutoutPath.reversing())
shadowMaskLayer.frame = maskFrame
shadowMaskLayer.path = maskPath.cgPath
}
}
// Shadow parameters are adjusted through `shadowLayer` property instead
let view = ShadowCutoutView()
view.shadowLayer.shadowOffset = .zero
view.shadowLayer.shadowColor = UIColor.black.cgColor
view.shadowLayer.shadowRadius = 20
view.shadowLayer.shadowOpacity = 1
// Shadow corner radius is determined by corner radius of the content view
let contentView = UIView()
contentView.clipsToBounds = true
contentView.layer.cornerRadius = 20
view.contentView = contentView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment