【问题标题】:Detect when UIView changes size during animation for shadow to move检测 UIView 在动画期间何时更改大小以移动阴影
【发布时间】:2019-05-27 12:13:30
【问题描述】:

UIView 子类中,我对override var bounds: CGRect 具有以下属性覆盖:

@IBDesignable
class GEView: UIView {

    private var shadowView: UIView? {
        didSet {
            guard let superview = superview else { return }
            guard let shadowView = self.shadowView else { return }

            // Add the shadow to the superview, as the shadow cannot
            // also allow rounded corners simultaneously
            superview.addSubview(shadowView)
            shadowView.layer.zPosition = layer.zPosition - 1
            shadowView.edges(to: self)
        }
    }

    // CALLED WHEN SETTING @IBInspectable PROPERTIES
    /// Creates a shadow if one has not yet been created.
    private func createShadowIfNeeded() {
        guard shadowView == nil else { return }

        shadowView = UIView()

        shadowView?.layer.shadowPath = UIBezierPath(roundedRect:    bounds,
                                                    cornerRadius:   cornerRadius).cgPath
        shadowView?.layer.shouldRasterize = true
    }


    // THE PROPERTY TO ATTEMPT THE SHADOW MOVING
    override var bounds: CGRect {
        didSet {
            shadowView?.layer.shadowPath = UIBezierPath(roundedRect:    bounds,
                                                        cornerRadius:   cornerRadius).cgPath
        }
    }
}

当视图约束被动画时(导致视图大小发生变化),当边界发生变化时,尝试多次重新绘制阴影。

但是,边界会立即改变,因为动画只是视觉上的。有没有办法让这个阴影在动画时跟随视图?如果这可以在UIView 子类中而不是在动画块中,那就更好了,即UIView.animate

问题如下:

我希望阴影在视图移动时跟随。在 gif 结束时,阴影位置和视图位置是正确的,因为覆盖忽略了动画并假装它已经动画了。

我该如何解决这个问题?

【问题讨论】:

    标签: ios swift uiview uiviewanimation shadow


    【解决方案1】:

    尝试更新layoutSubviews()中的shadowCustomView,即

    class CustomView: UIView {
        override func layoutSubviews() {
            super.layoutSubviews()
    
            self.layer.shadowRadius = 10.0
            self.layer.shadowOpacity = 1.0
            self.layer.shadowColor = UIColor.black.cgColor
    
            let oldPath = self.layer.shadowPath
            let newPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: 0.0).cgPath
            if oldPath != nil {
                let shadowPathAnimation: CABasicAnimation = CABasicAnimation(keyPath: "shadowPath")
                shadowPathAnimation.fromValue = oldPath
                shadowPathAnimation.toValue = newPath
                self.layer.add(shadowPathAnimation, forKey: "shadowAnimation")
                self.layer.shadowPath = newPath
            }
        }
    }
    
    class ViewController: UIViewController {
        @IBOutlet weak var customView: CustomView!
        @IBOutlet weak var trailingConstraint: NSLayoutConstraint!
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            UIView.animate(withDuration: 3.0) {
                self.trailingConstraint.constant = 200.0
                self.view.layoutIfNeeded()
            }
        }
    }
    

    【讨论】:

    • viewDidLayoutSubviews() 也不会从许多其他视图中触发吗?
    • @George_E 为什么不呢?
    • viewDidLayoutSubviews() 肯定会从其他地方触发。您可以检查是否已经设置了阴影细节。这只是一个示例,可以根据您的要求进行配置。
    • 这就是您如何为视图上的约束设置动画。
    • 问题是我有多个视图需要更新阴影。最好在我的 UIView 子类中这样做
    猜你喜欢
    • 2018-10-09
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多