LoginSignup
22
17

More than 5 years have passed since last update.

UIViewやUIWindowをドラッグで移動したりサイズ変える方法

Last updated at Posted at 2016-08-28

イメージ

こういうことがしたい人。

UIView_ChangeSizeAndMoveWindow.gif

解決方法

  • タップの検知
  • 移動かサイズ変更か判定
  • 移動量の反映

使用メソッド

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
22
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
17