AutoLayoutでアニメーションさせる話
この記事はYahoo! JAPAN 18 新卒 2 Advent Calendar 2018 18日目の記事です。
前回の記事は@jiazioさんのSRv6で8パズルを解いてみるでした。
1枚目はこちら Yahoo! JAPAN 18 新卒 Advent Calendar 2018
はじめに
最近、アプリにアニメーションとか入れてリッチにしたいなーと思ってるんですが、入社してデザイナーさんとも一緒に作業することも多く、アニメーションさせるにもAutoLayoutを使っている前提でのアニメーションなどが必要になる機会が増えてきたので、そのあたりをまとめてみたいと思います。
作るもの
アニメーションさせるにもなるべくコードを書かずに以下の様なアニメーションを実現します。
緑のViewに合わせてグレーのViewも変化していますが、やってることは緑のViewの左側の幅を変更しているだけです。
変更の仕方にも今回は2パターン記述します。
constantを変更する
緑のViewの左側のconstant
の変化をグレーのViewのwidthで吸収するイメージです。コードで変化させるNSLayoutConstraint
だけ、関連付けして値を動かせる様にします。
swift4.0
class ViewController: UIViewController {
@IBOutlet weak var leftConstraint: NSLayoutConstraint!
var isMoved = false
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func tappedButton(_ sender: UIButton) {
leftConstraint.constant = isMoved ? 50 : 100
isMoved = !isMoved
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}
もし、constantの値をベタ書きするのが嫌な場合は@IBInspectable
でstoryboard側に持たせましょう。この方がデザイナーさんに優しい。storyboardはこうなります。
swift4.0
class ViewController: UIViewController {
@IBInspectable var defaultConstant: CGFloat = 0.0
@IBInspectable var movedConstant: CGFloat = 0.0
@IBOutlet weak var leftConstraint: NSLayoutConstraint!
var isMoved = false
override func viewDidLoad() {
super.viewDidLoad()
leftConstraint.constant = defaultConstant
}
@IBAction func tappedButton(_ sender: UIButton) {
leftConstraint.constant = isMoved ? movedConstant : defaultConstant
isMoved = !isMoved
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}
isActiveで制約を使い分ける
次に、2つめのやり方として NSLayoutConstraint.isActive
を変更する方法があります。
先ほどと同じ動作をさせて見ましょう。
その際に緑のViewの左の幅の制約を2つ付ける必要があります。
素直に入れると以下の様に怒られます。
基本的に制約を付けると、priority = 1000
となっているので、移動後に有効にしたい制約のpriority
を下げて差を付けます。他の制約との兼ね合いを見ながら調整します。ここでは900にしてます。
この状態で、以下の様に実装すると同様の動きが得られます。
swift4.0
class ViewController: UIViewController {
@IBOutlet var defaultLeftConstraint: NSLayoutConstraint!
@IBOutlet var movedLeftConstraint: NSLayoutConstraint!
var isMoved = false
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func tappedButton(_ sender: UIButton) {
defaultLeftConstraint.isActive = !isMoved
movedLeftConstraint.isActive = isMoved
isMoved = !isMoved
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}
swift4.2
class ViewController: UIViewController {
@IBOutlet var defaultLeftConstraint: NSLayoutConstraint!
@IBOutlet var movedLeftConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func tappedButton(_ sender: UIButton) {
defaultLeftConstraint.isActive.toggle()
movedLeftConstraint.isActive.toggle()
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}
注意する点として、 NSLayoutConstraint
をweak
にしていると、isActive = falseのときに制約自体がnilになってしまうので、このやり方の場合は強参照で持たせましょう。
constantを変更する方がシンプルで簡単ですが、cellなどの利用して複雑な構成になってくるとisActiveで制約を使い分ける方法も有効になって来ます。
終わりに
サクッと触りの部分だけ書きましたが、もっと色々追求して行こうと思ってます。こんなのもあるよーなどあれば教えてくださいー!
追記
4.2からtoggle()が良いよって話があったので、それ用にもコード足しました。
Author And Source
この問題について(AutoLayoutでアニメーションさせる話), 我々は、より多くの情報をここで見つけました https://qiita.com/nokonoko2057/items/2defd645d8337a04c4fe著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .