0

I built a view with only the two upper corners that have a corner radius and the two bottom ones that are normal 90deg angles:

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
}

I add this to my view by simply doing:

override func layoutSubviews() {
    super.layoutSubviews()
    roundCorners(corners: [.topLeft, .topRight], radius: 15)
}

Now I want to add a shadow to it, and I tried doing the following:

private var shadowLayer: CAShapeLayer!
override func layoutSubviews() {
    super.layoutSubviews()

    let corners: UIRectCorner = [.topLeft, .topRight]
    let radius: CGFloat = 15

    roundCorners(corners: corners, radius: radius)

    if shadowLayer == nil {
        shadowLayer = CAShapeLayer()
        shadowLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)).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.3
        shadowLayer.shadowRadius = 2

        layer.insertSublayer(shadowLayer, at: 0)
    }
}

But this doesn't appear to work (the shadow is not appearing at all) How can I fix this?

Thank you

Nicop.dev
  • 50
  • 1
  • 8
  • I did not test, but it seems the shadow has exactly the size of the original. You should try to offset a few pixels right and down to create shadow right and down. – claude31 Jan 28 '20 at 16:17
  • @claude31 I tried to increase the shadowLayer.shadowOffset values but it doesn't change anything – Nicop.dev Jan 28 '20 at 16:19
  • I meant, change the path. – claude31 Jan 28 '20 at 16:20
  • To what path? @claude31 – Nicop.dev Jan 28 '20 at 16:25
  • Common issue. The problem is that to make a rounded corner, you need clipping - however clipping also cuts off the shadow. [Here is a similar question](https://stackoverflow.com/questions/24644802/swift-problems-with-corner-radius-and-drop-shadow), and there are many other similar questions if the answer isn't exactly here. – George Jan 28 '20 at 17:05
  • @George_E that's not the question: in that question they add a shadow only for the whole thing, but not only two corners, – Nicop.dev Jan 28 '20 at 17:28
  • @Nicop.dev I see you added your answer, and I was pointing to a similar concept. Of course it need to be adapted to your own needs. :) – George Jan 28 '20 at 17:56
  • Thank you, you made me get to this answer "you need clipping - however clipping also cuts off the shadow" made me think of this answer @George_E – Nicop.dev Jan 28 '20 at 17:59

1 Answers1

0

The solution I found:

private var shadowLayer: CAShapeLayer!
override func layoutSubviews() {
    super.layoutSubviews()

    self.backgroundColor = .clear
    self.layer.masksToBounds = false

    let radius: CGFloat = 30


    if shadowLayer == nil {
        shadowLayer = CAShapeLayer()
        shadowLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: radius, height: radius)).cgPath
// shadowLayer.path = UIBezierPath(roundedRect: CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.width, height: bounds.height), byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: radius, height: radius)).cgPath // To change the shadow shape
        shadowLayer.fillColor = UIColor.white.cgColor

        shadowLayer.shadowColor = UIColor.lightGray.cgColor
        shadowLayer.shadowPath = shadowLayer.path
        shadowLayer.shadowOffset = CGSize(width: 0, height: -2.0)
        shadowLayer.shadowOpacity = 0.1
        shadowLayer.shadowRadius = 4

        layer.insertSublayer(shadowLayer, at: 0)
    }
}

Unfortunately, this only hides the top corners, but they are still clickable if the View is a button.

Nicop.dev
  • 50
  • 1
  • 8