Определите, когда UIView изменяет размер во время анимации для перемещения тени - PullRequest
0 голосов
/ 27 мая 2019

В подклассе 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.

Вот как выглядит проблема:

Moving view gif

Я хочу, чтобы тень следовала, пока вид движется.В конце gif позиция тени и позиция просмотра верны, потому что переопределение игнорирует анимацию и делает вид, что оно уже анимировано.

Как это исправить?

1 Ответ

1 голос
/ 27 мая 2019

Попробуйте обновить shadow в layoutSubviews() из CustomView, т.е.

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()
        }
    }
}
...