状況
Youtubeチャンネルの素材用にTinderの模擬アプリを作成する際、
NSLayoutAnchor
での制約のActive
の切り替えてアニメーションをやりたかったのですが
なかなかうまくいかなかったのでメモ。
※NSLayoutAnchor
: コードでAutoLayout設定できる方法の1つ。
Storyboard
でいうところのAdd New Constraints
のような感覚で制約を設定できる。
やりたいこと
Tinderの模擬アプリにおいてtouchesEnded
(Viewから指を離す)したら
指を離した座標によって
- Viewを真ん中に戻す
- ViewをVC外に移動し削除する
どちらかの挙動を選択する
対策
NSLayoutAnchor使わない
やりたいことはViewの移動なので
直接中心座標を指定してアニメーションする
let screenWidth = self.view.frame.width
let screenHeight = self.view.frame.height
if viewCenter.x <= screenWidth/4 {
//Viewの中心座標が左右1/4にあれば最前面のViewを消す
UIView.animate(withDuration: 0.2, animations: {
draggedView!.center = CGPoint(x: -screenWidth/2, y: (screenHeight+64)/2)
}) { _ in //completion
draggedView!.removeFromSuperview()
self.girlsViewArray.removeLast()
}
} else if viewCenter.x >= 3*screenWidth/4 {
//Viewの中心座標が左右1/4にあれば最前面のViewを消す
UIView.animate(withDuration: 0.2, animations: {
draggedView!.center = CGPoint(x: 3*screenWidth/2, y: (screenHeight+64)/2)
}) { _ in //completion
draggedView!.removeFromSuperview()
self.girlsViewArray.removeLast()
}
} else {
//中心座標に戻したいので制約を有効にする //どうやら効いてない
UIView.animate(withDuration: 0.2) {
draggedView!.center = CGPoint(x: screenWidth/2, y: (screenHeight+64)/2)
draggedView!.likeView.alpha = 0
draggedView!.nopeView.alpha = 0
}
}
疑問点
このアニメーションをする前のdraggedView
の初期設定で
こんな感じでNSAutoLayout
でViewの位置をガッチリ固めていたのですが
view.center
やview.frame
を変更したら
制約を変更(false)しなくてもViewが動いたのが疑問。
frame
をハードコードしたら制約は無効になるの?? わかりません。。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
Array(0..<girlsViewArray.count).forEach {
//制約
girlsViewArray[$0].widthAnchor.constraint(equalTo: self.view.widthAnchor , constant: -2*margin).isActive = true
girlsViewArray[$0].heightAnchor.constraint(equalTo: self.view.heightAnchor, constant: -(44+20)-2*margin).isActive = true
//44.0(navHeight) + 20.0(statusBarHeight) + 2*10(margin)
girlsViewArray[$0].centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
girlsViewArray[$0].centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: (44+20)/2).isActive = true
//44.0(navHeight) + 20.0(statusBarHeight)
}
}
・UIKitのView表示ライフサイクルを理解する - Qiita
->この記事にあるように
- Viewの読み込み
- 制約の追加(AutoLayout)
- 制約を元にViewのframeを計算(レイアウト)
- frameの位置に描画(レンダリング)
の順番だとすれば、frame
をハードコードしたら制約が無効になるのも納得がいくかも。。。
参考
・iOS, AutoLayoutで簡単にできるアニメーション - Qiita
・UIKitのView表示ライフサイクルを理解する - Qiita