I'm trying to create a shadow on the top a view.
This is my hierarchy:
View
------TablewView
------BottomView
TableView and BottomView have the same parent: View.
I want the BottomView to have a shadow on top of the TableView like the pic on the left, but the result is the one on the right:
If I try to remove the TableView I see the shadow. The BottomView haves rounded corners. This is the BottomView Class:
class BottomView: UIView {
private var shadowLayer: CAShapeLayer!
override func layoutSubviews() {
super.layoutSubviews()
if shadowLayer == nil {
let shadowLayer = CAShapeLayer()
shadowLayer.masksToBounds = false
//rect is an ex.
shadowLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 200, height: 80), cornerRadius: 9).cgPath
shadowLayer.fillColor = UIColor.red.cgColor
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowOffset = CGSize(width: 5, height: -5)
shadowLayer.shadowOpacity = 1
shadowLayer.shadowRadius = 3
shadowLayer.zPosition = 10
layer.insertSublayer(shadowLayer, at: 0)
clipsToBounds = false
}
}
}
The first issue is variable / object scope...
class BottomView: UIView {
private var shadowLayer: CAShapeLayer!
override func layoutSubviews() {
super.layoutSubviews()
if shadowLayer == nil {
let shadowLayer = CAShapeLayer()
...
Where you say: let shadowLayer = CAShapeLayer()
, you just created a new, local shadowLayer
object, and it disappears when it goes out of scope (at the end of the if
block).
Change that line to:
shadowLayer = CAShapeLayer() // remove the let
and you should see your shadow.
You can "automate" the sizing, by adding this below the if
block:
if shadowLayer != nil {
shadowLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height), cornerRadius: 9).cgPath
}
that will re-size the shadow layer anytime the view changes size.