aqsa arshad
aqsa arshad

Reputation: 831

Shadow effect is not displaying properly for UIView

I have a login screen as below. Around each text field I have added a view and for that view I want to display a drop shadow. I kind of achieved what I was trying but this thing is not working for iPhone Plus (6+,8+) devices.

You can see the difference below.

iPhone 8+:-

enter image description here

iPhone 8:-

enter image description here

Here is my code

extension UIView {
    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

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

How I can fix this properly?

Upvotes: 6

Views: 2870

Answers (3)

Latenec
Latenec

Reputation: 418

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.

Upvotes: 2

clemens
clemens

Reputation: 17711

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.

Upvotes: 5

Ankit Jayaswal
Ankit Jayaswal

Reputation: 5669

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
}

Upvotes: 2

Related Questions