ホーム » Swift » 【Swift】UIView.animateがうまくいかない?Viewに制約をかけていませんか?その対処方法(CGAffinTransForm)

【Swift】UIView.animateがうまくいかない?Viewに制約をかけていませんか?その対処方法(CGAffinTransForm)

【Swift】UIView.animateがうまくいかない?Viewに制約をかけていませんか?その対処方法(CGAffinTransForm) Swift

はじめに

・制約をかけたオブジェクトに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の学習であればこれ一冊で十分だと思います。

コメント

タイトルとURLをコピーしました