새소식

iOS/UIKit

[UIKit][코드베이스] Drag and Drop Picture

  • -

[참고영상]

https://youtu.be/cOcjrmFp2v8


[학습 목표]

이미지를 드래그 & 드롭하거나 드롭했을시 원래 위치로 돌아오게 만들자.


[구현 방법]

1. viewDidLoad 안쪽에 imageView와 card뷰를 만들자. 

2. "DALL"이라는(혹은 다른 이름의) 이미지를 Asset안에 넣어두자.

fileprivate let imageView = UIImageView(image: UIImage(named: "DALL"))

override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(imageView)
        imageView.contentMode = .scaleAspectFill
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        imageView.heightAnchor.constraint(equalToConstant: 450).isActive = true
        imageView.widthAnchor.constraint(equalToConstant: 275).isActive = true
        
        imageView.clipsToBounds = true
        imageView.layer.cornerRadius = 30
        
        let card = UIView()
        imageView.addSubview(card)
        card.translatesAutoresizingMaskIntoConstraints = false
        card.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        card.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        card.heightAnchor.constraint(equalToConstant: 450).isActive = true
        card.widthAnchor.constraint(equalToConstant: 275).isActive = true
        card.backgroundColor = UIColor.blue.withAlphaComponent(0.67)
    }

 

3. 이미지를 움직일때 동작을 시킬 handlePanGesture 함수를 만들어주자.

@objc func handlePanGestrue(gesture: UIPanGestureRecognizer) {    
    if gesture.state == .began {
        print("began")
    } else if gesture.state == .changed {
        let translation = gesture.translation(in: self.view)
        imageView.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
    } else if gesture.state == .ended {
        UIView.animate(withDuration: 0.8, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
            self.imageView.transform = .identity
        })
    }
}

해당 함수는 UIPanGestrueRecognizer를 이용하며 이동의 시작(began), 이동의 중간(changed), 이동의 끝(ended)의 3개의 상태 변화를 파악한다.

changed를 이용해서 이미지를 움직이게 만들고 ended를 이용해서 이미지를 원상복귀 시킨다.

CGAffineTransform 함수를 이용해서 움직이는 x와 y의 위치를 파악하자. (만일 y나 x를 0으로 둔다면 수직이나 수평으로만 움직이는 것을 볼 수가 있을 것이다.)

만일 ended 내부에 있는 내용을 지운다면 이미지가 움직인 상태 그대로 멈출 것이다.

 

4. viewDidLoad 내부에  카드와 imageView가 움직일수 있게 만들자.

card.isUserInteractionEnabled = false
imageView.isUserInteractionEnabled = true

imageView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.handlePanGestrue)))

보면 card의 경우에는 InteractionEnabled가 false인데도 불구하고 image와 같이 움직이는 것을 확인 할 수가 있다.

이를 통해서 뷰를 움직였을때 해당 뷰 윗쪽에 있는 계층들도 같이 해당 뷰를 따라서 움직이는 것을 알 수가 있다.


[전체 코드]

import UIKit

class ViewController: UIViewController {
    
    fileprivate let imageView = UIImageView(image: UIImage(named: "DALL"))
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(imageView)
        imageView.contentMode = .scaleAspectFill
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        imageView.heightAnchor.constraint(equalToConstant: 450).isActive = true
        imageView.widthAnchor.constraint(equalToConstant: 275).isActive = true
        
        imageView.clipsToBounds = true
        imageView.layer.cornerRadius = 30
        
        let card = UIView()
        imageView.addSubview(card)
        card.translatesAutoresizingMaskIntoConstraints = false
        card.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        card.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        card.heightAnchor.constraint(equalToConstant: 450).isActive = true
        card.widthAnchor.constraint(equalToConstant: 275).isActive = true
        card.backgroundColor = UIColor.blue.withAlphaComponent(0.67)
        
        card.isUserInteractionEnabled = false
        imageView.isUserInteractionEnabled = true
        
        imageView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.handlePanGestrue)))
    }
    
    @objc func handlePanGestrue(gesture: UIPanGestureRecognizer) {
        
        if gesture.state == .began {
            print("began")
        } else if gesture.state == .changed {
            let translation = gesture.translation(in: self.view)
            imageView.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        } else if gesture.state == .ended {
            UIView.animate(withDuration: 0.8, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
                self.imageView.transform = .identity
            })
        }
    }
}

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.