はじめに
・制約をかけたオブジェクトにUIView.animatで位置のアニメーションをかけてもうまく動いてくれないことがあるかと思います。
・私もハマったので備忘録として残しておきます。
環境
・Swift 5.7.2
・Xcode 14.2
・iOS 16.2
制約をかけていないオブジェクトにUIView.animate
これは意図通りに動きます。

import UIKit
class ViewController: UIViewController {
var blueView:UIView!
override func viewDidLoad() {
super.viewDidLoad()
blueView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
blueView.backgroundColor = .systemBlue
blueView.center = view.center
view.addSubview(blueView)
print(view.center)
}
@IBAction func clickButton(_ sender: UIButton) {
blueView.center = view.center
UIView.animate(withDuration: 1.0, delay: 0.0, options: [.curveLinear], animations: {
self.blueView.center.y += 100
}){ (completed) in
}
}
}
制約をかけて同じ処理をした場合
中央にwidth:50、height:50で制約をかけます。
viewの名前は同じコードとするためblueViewです。

先ほどと全く同じコードです。
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var blueView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
print(view.center)
}
@IBAction func clickButton(_ sender: UIButton) {
blueView.center = view.center
UIView.animate(withDuration: 1.0, delay: 0.0, options: [.curveLinear], animations: {
self.blueView.center.y += 100
}){ (completed) in
}
}
}

先ほどとは全く違った動きになります。
両方並べるとこうなります。


なぜこうなるのか?私見です。
これは私の考察になるのですが、制約を入れた場合に制約から外れると必ずその制約に戻ろうとする制約のアニメーションが発生します。y方向に動くアニメーションと制約のアニメーションが競合(組み合わされて)、制約通りの位置にy方向に動くアニメーションとなって描画されるのだと思います。
対処方法:CGAffineTransformを使う
先ほどの制約をつけたViewで想定通りの動きを実現したい場合は「CGAffinTransForm」を使えば実現可能です。
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var blueView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
print(view.center)
}
@IBAction func clickButton(_ sender: UIButton) {
UIView.animate(withDuration: 1.0, delay: 0.0, options: [.curveLinear], animations: {
self.blueView.transform = CGAffineTransform(translationX: 0, y: 100)
}){ (completed) in
self.blueView.transform = CGAffineTransform(translationX: 0, y: 0)
}
}
}
動きは想定通りになります。

まとめ
・制約をつけたViewにアニメーションをかける場合はCGAffinTransFormを使うとよい
Swiftのおすすめ参考書籍
Swiftの詳しい文法や標準ライブラリの使い方など基礎を学ぶことが出来ます。プログラミング言語としてのSwiftの学習であればこれ一冊で十分だと思います。
コメント