PanGestureの実装方法が間違っているのに最近気づいたため、備忘録として残します。
一つViewを作る
ViewController.swift
import UIKit
class ViewController: UIViewController {
let blueView = {
let view = UIView()
view.backgroundColor = .blue
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(blueView)
}
override func viewDidLayoutSubviews() {
blueView.frame = CGRect(x: 30, y: 30, width: 100, height: 50)
}
}
次にPanGestureをつける
私はこんな感じで実装していました。一応動きます。
ViewController.swift
import UIKit
class ViewController: UIViewController {
let blueView = {
let view = UIView()
view.backgroundColor = .blue
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
//追加
blueView.isUserInteractionEnabled = true
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture))
blueView.addGestureRecognizer(panGesture)
view.addSubview(blueView)
}
override func viewDidLayoutSubviews() {
blueView.frame = CGRect(x: 30, y: 30, width: 100, height: 50)
}
//追加
@objc func panGesture(sender: UIPanGestureRecognizer){
let point = sender.location(in: view)
let panGesture = sender.view
panGesture?.center = point
}
}
ただこれだとViewが小さいときは気にならないのですが、viewのサイズが大きい時(width :300, height:300くらい)ぎこちない動きになります。原因はこのpanGestureメソッドです。
@objc func panGesture(sender: UIPanGestureRecognizer){
//①クリックした地点の座標を取得
let point = sender.location(in: view)
let panGesture = sender.view
//②viewの中心座標をクリックした地点の座標に無理やり設定している
panGesture?.center = point
}
移動量を使おう
メソッドを以下のように変更するとスムーズに移動します。@objc func panGesture(sender: UIPanGestureRecognizer){
//viewをドラッグした時の移動量を取得
let move = sender.translation(in: view)
let panGesture = sender.view
//移動量をviewの中心のx座標、y座標に足してあげます
panGesture?.center.x += move.x
panGesture?.center.y += move.y
//最後に移動量をリセットしてあげます。この文がないとviewがどこかに飛んでいきます。
sender.setTranslation(.zero, in: view)
}
全体のコード
import UIKit
class ViewController: UIViewController {
let blueView = {
let view = UIView()
view.backgroundColor = .blue
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
blueView.isUserInteractionEnabled = true
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture))
blueView.addGestureRecognizer(panGesture)
view.addSubview(blueView)
}
override func viewDidLayoutSubviews() {
blueView.frame = CGRect(x: 30, y: 30, width: 300, height: 300)
}
@objc func panGesture(sender: UIPanGestureRecognizer){
let move = sender.translation(in: view)
let panGesture = sender.view
panGesture?.center.x += move.x
panGesture?.center.y += move.y
sender.setTranslation(.zero, in: view)
}
}