イメージ
こういうことがしたい人。
解決方法
- タップの検知
- 移動かサイズ変更か判定
- 移動量の反映
使用メソッド
UIView.touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
UIView.touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
UIView.touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
UITouch.locationInView(UIView?) -> UIPoint
CGRect.offsetBy(dx dx: CGFloat, dy: CGFloat) -> CGRect
何をやってるか
- タッチ開始時
- タッチ場所から位置移動なのかサイズ変更判定
- タッチ位置を初期タッチ位置を対象ビューの相対位置として記憶
- タッチ移動時
- サイズ変更の場合
- UIView.frame のサイズ部分のみを変更
- 位置移動の場合
- タップ位置と初期相対位置を UIView.frame に反映
- サイズ変更の場合
なぜ初期タッチ位置が必要なのか?
これを外して移動させると、タップ位置にビューの左上(Origin)が来てしまい、操作性が悪くなる。
サイズ変更はこれをしてないため、タップ位置にビューの右下(Origin+Size)がきてる。
コード全文
疲れたので まとめとして下記にコード全文
class MyView : UIView
{
enum BehaviorMode : Int{
case None
case MoveWindowPosition
case ChangeWindowSize
}
private var behaviorMode:BehaviorMode = .None
private var locationInitialTouch:CGPoint!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 0.7)
self.userInteractionEnabled = true
self.windowLevel = UIWindowLevelAlert
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
let location = touch.locationInView(self)
print("Began:(\(location.x), \(location.y))")
locationInitialTouch = location
if location.x > bounds.width - 20 && location.y > bounds.height - 20{
behaviorMode = .ChangeWindowSize
}else{
behaviorMode = .MoveWindowPosition
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
let location = touch.locationInView(self)
print("Moved:(\(location.x), \(location.y))")
if behaviorMode == .ChangeWindowSize {
frame = CGRect(origin: frame.origin, size: CGSize(width: location.x, height: location.y ))
}else{
frame = frame.offsetBy(dx: location.x - locationInitialTouch.x, dy: location.y - locationInitialTouch.y)
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
let location = touch.locationInView(self)
print("Ended:(\(location.x), \(location.y))")
if behaviorMode == .ChangeWindowSize {
frame = CGRect(origin: frame.origin, size: CGSize(width: location.x, height: location.y ))
}else{
frame = frame.offsetBy(dx: location.x - locationInitialTouch.x, dy: location.y - locationInitialTouch.y)
}
behaviorMode = .None
}
}
}
もしタップ検知しない場合
UIView.userInteractionEnabled = true