Shadow effect is not displaying properly for UIView

Since the views may be resized you should update your shadowPath after resizing because it has a fixed size. Unfortunately this can't be done in an extension, because you need to overwrite layoutSubview(). But you may call addShadow() from viewDidLayoutSubviews() from your view controller again for each text field.

You may also modify your extension to only update the path:

extension UIView {
    func addShadow() {        
        layer.cornerRadius = 8

        layer.shadowColor = UIColor.lightGray.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 1.0)
        layer.shadowRadius = 2.0
        layer.shadowOpacity = 0.5
        layer.masksToBounds = false

        updateShadow()
    }
    func updateShadow() {
        layer.shadowPath = UIBezierPath(roundedRect: self.bounds,cornerRadius:8).cgPath
    }  
}

With this you should call updateShadow() from viewDidLayoutSubviews() for each view with a shadow.

If you use a custom subclass for your text fields you may put the updateShadow() call into layoutSubviews(). So you need not to call it from the view controller.


You are building the view on iPhone 8 on storyboard. So when you run it on iPhone 8+/ 6+, view gets resized but shadow does not get updated.

enter image description here

Put layoutIfNeeded() before adding shadowPath to layer:

Updated code will look like:

func addShadow() {
    layer.cornerRadius = 8
    layer.masksToBounds = true

    layer.shadowColor = UIColor.lightGray.cgColor
    layer.shadowOffset = CGSize(width: 0, height: 1.0)
    layer.shadowRadius = 2.0
    layer.shadowOpacity = 0.5
    layer.masksToBounds = false

    layoutIfNeeded()
    layer.shadowPath = UIBezierPath(roundedRect: self.bounds,cornerRadius: 8).cgPath
}

I'm sharing my approach that worked for me. I have used @clemens extension which is:

extension UIView {
    func addShadow() {        
        layer.cornerRadius = 8
        layer.shadowColor = UIColor.lightGray.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 1.0)
        layer.shadowRadius = 2.0
        layer.shadowOpacity = 0.5
        layer.masksToBounds = false

        updateShadow()
    }

    func updateShadow() {
        layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: 8).cgPath
    }  
}

However, it didn't work until this:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Async is the key in this situation :)
    DispatchQueue.main.async { [weak self] in
        self?.someButton.addShadowNice()
        self?.someButton.updateShadow()
    }
}

Cheers.

Tags:

Ios

Swift