【Swift/UIKit】ドラッグで UIView を動かす
スーッと指で UIView を動かす処理を書き置き。
ドラッグ中に細かく何度も呼び出されるメソッド touchesMoved(_:with:) を使用する。
イメージ
メソッドで行う処理のイメージはこんな感じ
- 指でドラッグを開始した位置(座標)と終了した(動かしてる途中でも一区切りの中で)位置を取得
- 開始位置と終了位置から移動距離を出す
- 移動した分を UIView の元の位置に足して反映
指を動かしている間、メソッドが呼ばれるたびにこの流れを繰り返す
コード
UIView を用意。ここではラベルを。
var sampleLabel: UILabel!
isUserInteractionEnabled を忘れずに。これでタッチを感知することを許可する。
sampleLabel = UILabel() sampleLabel.frame = CGRect(x: 0, y: 0, width: 100, height: 50) sampleLabel.center = self.view.center sampleLabel.textAlignment = .center sampleLabel.backgroundColor = .black sampleLabel.textColor = .white sampleLabel.text = "Move me!" //タッチを受け付ける(デフォルトは false) sampleLabel.isUserInteractionEnabled = true self.view.addSubview(sampleLabel)
何度も呼ばれるメソッド内の処理。動かしたいものに触れた時だけ実行したいので、タッチイベントの情報を使って条件分岐。
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { //タッチイベント let aTouch = touches.first! //タッチされたものがラベルの場合 if aTouch.view == sampleLabel { //指の移動先の座標 let destLocation = aTouch.location(in: self.view) //指の移動前の座標 let prevLocation = aTouch.previousLocation(in: self.view) //取得した座標を格納する変数 var myFrame = sampleLabel.frame //X,Yの移動距離 let deltaX = destLocation.x - prevLocation.x let deltaY = destLocation.y - prevLocation.y //移動距離分を足す myFrame.origin.x += deltaX myFrame.origin.y += deltaY //反映 sampleLabel.frame = myFrame } }
好みでタッチ開始、終了時にアニメーション
//タッチを感知した時に呼ばれるメソッド override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if touches.first?.view == sampleLabel { UIView.animate(withDuration: 0.06, animations: { self.sampleLabel.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) }) { (Bool) in } } }
//指を離した時に呼ばれるメソッド override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { if touches.first?.view == sampleLabel { UIView.animate(withDuration: 0.1, animations: { self.sampleLabel.transform = CGAffineTransform(scaleX: 0.4, y: 0.4) self.sampleLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) }) { (Bool) in } } }