我想要的确切结果是将faceView
的绘图内容的边界与faceView
的边界一起包括在设备旋转动画中
相反,backgroundColor
已正确设置为动画,并显示faceView
的边界已设置为动画。但是,就在旋转动画开始之前,形状突然改变为其新的大小和颜色。
我尝试过的似乎无济于事的是,在关键帧动画中使用以下内容实现viewWillTransition
。
self.setColors()
self.faceView.updatePath()
我看不出如何使形状的路径和填充颜色包含在动画中。
ViewController
class ViewController: UIViewController {
lazy var faceView = FaceView()
var colorSwitch = true
var faceViewConstraints = [NSLayoutConstraint]()
override func loadView() {
super.loadView()
self.view.addSubview(faceView)
self.faceView.viewFrame = self.faceView.bounds
setupConstraints()
activateConstraints()
}
override func viewDidLoad() {
super.viewDidLoad()
self.setColors()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: {_ in
UIView.animateKeyframes(withDuration: coordinator.transitionDuration, delay: 0, animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1) {
self.setColors()
self.faceView.updatePath()
}
})
})
}
private func setColors() {
if (colorSwitch) {
self.faceView.backgroundColor = .red
self.faceView.shapeFillColor = .blue
} else {
self.faceView.backgroundColor = .blue
self.faceView.shapeFillColor = .red
}
self.colorSwitch = !self.colorSwitch
}
private func setupConstraints() {
let safeArea = view.safeAreaLayoutGuide
let aspectConstraint = faceView.widthAnchor.constraint(equalTo: faceView.heightAnchor, multiplier: 9/16)
let centerXConstraint = faceView.centerXAnchor.constraint(equalTo: faceView.superview!.centerXAnchor)
let centerYConstraint = faceView.centerYAnchor.constraint(equalTo: faceView.superview!.centerYAnchor)
// medium high priority constraints
let leadingConstraintMedHigh = faceView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: 10)
leadingConstraintMedHigh.priority = UILayoutPriority(750)
let trailingConstraintMedHigh = faceView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor, constant: 10)
trailingConstraintMedHigh.priority = UILayoutPriority(750)
let topConstraintMedHigh = faceView.topAnchor.constraint(equalTo: safeArea.topAnchor, constant: 10)
topConstraintMedHigh.priority = UILayoutPriority(750)
let bottomConstraintMedHigh = faceView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor, constant: 10)
bottomConstraintMedHigh.priority = UILayoutPriority(750)
// required constraints
let leadingConstraintHigh = faceView.leadingAnchor.constraint(greaterThanOrEqualTo: safeArea.leadingAnchor, constant: 10)
leadingConstraintHigh.priority = UILayoutPriority(1000)
let trailingConstraintHigh = faceView.trailingAnchor.constraint(lessThanOrEqualTo: safeArea.trailingAnchor, constant: 10)
trailingConstraintHigh.priority = UILayoutPriority(1000)
let topConstraintHigh = faceView.topAnchor.constraint(greaterThanOrEqualTo: safeArea.topAnchor, constant: 10)
topConstraintHigh.priority = UILayoutPriority(1000)
let bottomConstraintHigh = faceView.bottomAnchor.constraint(lessThanOrEqualTo: safeArea.bottomAnchor, constant: 10)
bottomConstraintHigh.priority = UILayoutPriority(1000)
faceViewConstraints = [aspectConstraint, centerXConstraint, centerYConstraint, leadingConstraintMedHigh, trailingConstraintMedHigh, topConstraintMedHigh, bottomConstraintMedHigh, leadingConstraintHigh, trailingConstraintHigh, topConstraintHigh, bottomConstraintHigh]
}
private func activateConstraints() {
NSLayoutConstraint.activate(faceViewConstraints)
}
}
View Class
class FaceView: UIView {
// use custom root layer
override class var layerClass: AnyClass {
return CAShapeLayer.self
}
var viewFrame = CGRect.zero {
didSet {
self.circleBounds = viewFrame.insetBy(dx: lineW/2, dy: lineW/2)
}
}
var circleBounds = CGRect.zero
var lineW: CGFloat = 3
var myLayer: CAShapeLayer!
var shapeFillColor = UIColor.blue
override init(frame: CGRect) {
super.init(frame: frame)
self.translatesAutoresizingMaskIntoConstraints = false
myLayer = self.layer as? CAShapeLayer
updatePath()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
myLayer.contentsScale = UIScreen.main.scale
myLayer.lineWidth = lineW
myLayer.fillColor = shapeFillColor.cgColor
myLayer.strokeColor = UIColor.black.cgColor
viewFrame = self.bounds
updatePath()
}
func updatePath() {
myLayer.fillColor = shapeFillColor.cgColor
viewFrame = self.bounds
let p = CGMutablePath()
p.addEllipse(in: circleBounds)
myLayer.path = p
}
}
我不清楚您要达到的确切结果,但是通常要知道的关键是:如果实现viewWillLayoutSubviews
,并且在该实现中是否更改了视图的约束或框架(取决于视图是否受自动布局影响),这些更改将与内置的旋转动画一起进行动画处理。
或者(并且不相关),您可以实现viewWillTransition
或willTransition
,获取过渡协调器,并调用其animate(alongsideTransition:completion:)
。同样,您在此处执行的任何动画都将成为旋转动画的一部分。