CALAyer
どこからともなく現れるようにアニメーション化したいと思います。最初にレイヤーの変換を「x:0、y:0にスケーリング」に設定できると思いました。次に、アニメーションを実行して、変換を「x: 1、y: 1 にスケール」に設定します。これがアイデンティティです。これにより、レイヤーがゼロから拡大されたように見えると思いました。しかし、これを実装しようとすると、アニメーションなしでレイヤーがすぐに表示されました。
MCVE:
class MyView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
backgroundColor = .clear
clipsToBounds = false
setupLayers()
}
var squareLayer: CAShapeLayer!
private func setupLayers() {
layer.sublayers?.forEach { $0.removeFromSuperlayer() }
squareLayer = CAShapeLayer()
layer.addSublayer(squareLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
drawLayers()
}
func drawLayers() {
squareLayer.fillColor = UIColor.red.cgColor
squareLayer.path = UIBezierPath(rect: bounds).cgPath
squareLayer.frame = bounds
}
}
次に、私のVCで:
@IBAction func click() {
myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
view.addSubview(myView)
myView.drawLayers()
myView.squareLayer.setAffineTransform(.init(scaleX: 0, y: 0))
CATransaction.begin()
CATransaction.setAnimationDuration(1)
self.myView.squareLayer.setAffineTransform(.init(scaleX: 1, y: 1))
CATransaction.commit()
}
これは、最初の呼び出しもアニメーション化されているためだと思いましたsetAffineTransform
(なぜそれが影響するのか正確にはわかりませんでしたが、影響があるのではないかと疑っていました)。そのため、2 番目の呼び出しを完了ブロックに移動しようとしました。
@IBAction func click() {
myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
view.addSubview(myView)
myView.drawLayers()
CATransaction.begin()
CATransaction.setCompletionBlock {
CATransaction.begin()
CATransaction.setAnimationDuration(1)
self.myView.squareLayer.setAffineTransform(.init(scaleX: 1, y: 1))
CATransaction.commit()
}
myView.squareLayer.setAffineTransform(.init(scaleX: 0, y: 0))
CATransaction.commit()
}
ただし、出力は同じです。一方、最初のsetAffineTransform
呼び出しの後に少し待つと、次のように機能します。
@IBAction func click() {
myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
view.addSubview(myView)
myView.drawLayers()
myView.squareLayer.setAffineTransform(.init(scaleX: 0, y: 0))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
CATransaction.begin()
CATransaction.setAnimationDuration(1)
self.myView.squareLayer.setAffineTransform(.init(scaleX: 1, y: 1))
CATransaction.commit()
}
}
しかし、これがこの問題を解決する方法だとは思いません。おそらく、その間に何らかのライフサイクル メソッドが呼び出され (どれかはわかりません)、setAffineTransform
そのライフサイクル メソッドの後に 2 回目の呼び出しを行う必要があります... (?)
代わりにこれを使用できることはわかっていますCABasicAnimation
が、アニメーションの終わりを検出するためにデリゲートを使用する必要がある方法が好きではありません。これは私にとって多くのことを非常に面倒にします。0.1秒遅らせるのが効いたので、これはCATransaction
sで無理じゃないですよね?
CALayer
アニメーションを使用して表示するにはどうすればよいですか?