UIView的阴影效果显示不正确。

6
我有一个如下的登录界面。我在每个文本字段周围添加了一个视图,并为该视图添加了一个下拉阴影。虽然我已经实现了我想要的效果,但是这种方式在iPhone Plus(6+、8+)设备上无法工作。
您可以在下面看到差异。
iPhone 8 +:- enter image description here iPhone 8:- enter image description here 以下是我的代码:
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
    }
}

我该如何正确修复这个问题?

你的代码是正确的。前往Storyboard,打开Attribute Inspector,选择Simulated Metrics,设置Size为iPhone 8+,然后检查你所面临的确切问题。 - user9137841
附加的图片是模拟器的截图,但我也尝试在实际设备上运行过。 - aqsa arshad
你已经收到了两个回答,从逻辑上都是正确的...不妨试一试! - TheTiger
仅供参考:viewDidLayoutSubviews()会被多次调用,因此不要在此处进行任何添加工作(layerview),对于图层而言,它会添加多个图层,阴影看起来会更暗。 - TheTiger
当然。谢谢 :) - aqsa arshad
显示剩余3条评论
3个回答

5

由于视图大小可能会改变,因此在调整大小后应更新shadowPath,因为它具有固定的大小。不幸的是,这不能在扩展中完成,因为您需要覆盖layoutSubview()。但是,您可以从您的视图控制器的viewDidLayoutSubviews()再次为每个文本字段调用addShadow()

您还可以修改您的扩展以仅更新路径:

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
    }  
}

使用这个方法,你应该在每一个带有阴影的视图中从viewDidLayoutSubviews()调用updateShadow()

如果你为文本框使用自定义子类,你可以将updateShadow()调用放入layoutSubviews()中。因此你不需要从视图控制器中调用它。


2
你正在Storyboard上构建iPhone 8的视图。因此,当你在iPhone 8+/6+上运行它时,视图会被重新调整大小,但阴影不会被更新。

enter image description here

在将shadowPath添加到layer之前,请使用layoutIfNeeded()

更新后的代码如下:
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
}

1
在设备旋转或其他视图调整之后,这将无法工作。 - clemens
1
@clemens 正确,但对于这个问题可以工作。因此我们不能说它是错误的! - TheTiger
1
@aqsaarshad,如果您只使用纵向模式,则可以正常工作。 - Ankit Jayaswal
还支持横屏。 - aqsa arshad
@TheTiger:我从未说过它是错误的。它并不适用于所有情况。在iPad上使用分屏时,它将无法调整阴影大小。 - clemens

2

我分享一下我成功的方法。我使用了@clemens的扩展,它是:

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
    }  
}

然而,直到采用了以下方法才成功:
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Async is the key in this situation :)
    DispatchQueue.main.async { [weak self] in
        self?.someButton.addShadowNice()
        self?.someButton.updateShadow()
    }
}

干杯。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接