iOS 응용 (swift)
[iOS - swift] UICollectionView에서 원하는 뷰 영역만 드래그 할 때 보이도록 하는 방법 (itemsForBeginning, dragInteractionEnabled, dragDelegate, dropDelegate)
jake-kim
2023. 8. 3. 01:10
UICollectionView의 Drag & Drop
- UICollectionView에서 dragInteractionEnabled = true하면 drag & drop을 구현할 수 있고, dragDelegate, dropDelegate를 구현하면 데이터 처리가 가능

drag할 때 특정 뷰만 보이게끔 하는 방법?
- 만약 cell을 타원 형태로 만들고 싶을 때, drag & drop을 하게되면 cell의 사각형 영역만큼 하얀색 영역이 생성됨

(이동시킬 때 보라색 바깥쪽에 cell의 하얀색 색상이 생성된 형태)

- UICollectionViewDragDelegate의 itemsForBeginning을 사용하면 쉽게 구현이 가능
드래그 할 때 특정 뷰만 구현 방법 구현
1). UICollectionViewDragDelegate의 itemsForBeginning를 수정하여 구현
2). itemsForBeginning 메소드 안에서 UIDragItem의 배열들을 리턴하게 되는데, UIDragItem안에 previewProvider를 사용하여 프리뷰의 정보 세팅이 가능
3). previewProvider의 값에 보여줄 뷰와 그 뷰의 rect, cornerRadius값을 설정할 수 있는데 이것을 사용하면 구현 완료
- 1. UICollectionViewDragDelegate의 itemsForBeginning를 수정하여 구현
(기존 코드)
// 기존 코드
extension ViewController: UICollectionViewDragDelegate {
func collectionView(
_ collectionView: UICollectionView,
itemsForBeginning session: UIDragSession,
at indexPath: IndexPath
) -> [UIDragItem] {
[UIDragItem(itemProvider: NSItemProvider())]
}
}
- 구현부 안에 필요한 UIDragItem 인스턴스 선언
// 기존 코드
extension ViewController: UICollectionViewDragDelegate {
func collectionView(
_ collectionView: UICollectionView,
itemsForBeginning session: UIDragSession,
at indexPath: IndexPath
) -> [UIDragItem] {
// 1.
let itemProvider = NSItemProvider()
let dragItem = UIDragItem(itemProvider: itemProvider)
// TODO
}
}
- 2. itemsForBeginning 메소드 안에서 UIDragItem의 배열들을 리턴하게 되는데, UIDragItem안에 previewProvider를 사용하여 프리뷰의 정보 세팅이 가능
- 표시해줄 뷰를 cell에서부터 획득
- snapshotView()를 통해서 표시해줄 뷰를 복사 (snapshotView 개념은 이전 포스팅 글 참고)
// 기존 코드
extension ViewController: UICollectionViewDragDelegate {
func collectionView(
_ collectionView: UICollectionView,
itemsForBeginning session: UIDragSession,
at indexPath: IndexPath
) -> [UIDragItem] {
// 1.
let itemProvider = NSItemProvider()
let dragItem = UIDragItem(itemProvider: itemProvider)
// 2.
guard
let targetView = (collectionView.cellForItem(at: indexPath) as? MyCell)?.contentView,
let dragPreview = targetView.snapshotView(afterScreenUpdates: false)
else {
return [UIDragItem(itemProvider: NSItemProvider())]
}
// TODO
}
}
- 3. previewProvider의 값에 보여줄 뷰와 그 뷰의 rect, cornerRadius값을 설정할 수 있는데 이것을 사용하면 구현 완료
// 기존 코드
extension ViewController: UICollectionViewDragDelegate {
func collectionView(
_ collectionView: UICollectionView,
itemsForBeginning session: UIDragSession,
at indexPath: IndexPath
) -> [UIDragItem] {
// 1.
let itemProvider = NSItemProvider()
let dragItem = UIDragItem(itemProvider: itemProvider)
// 2.
guard
let targetView = (collectionView.cellForItem(at: indexPath) as? MyCell)?.contentView,
let dragPreview = targetView.snapshotView(afterScreenUpdates: false)
else {
return [UIDragItem(itemProvider: NSItemProvider())]
}
// 3.
let previewParameters = UIDragPreviewParameters()
previewParameters.visiblePath = UIBezierPath(
roundedRect: dragPreview.bounds,
cornerRadius: targetView.layer.cornerRadius
)
dragItem.previewProvider = { () -> UIDragPreview? in
UIDragPreview(view: dragPreview, parameters: previewParameters)
}
return [dragItem]
}
}
(완료)

(셀의 테두리가 정상적으로 제거되고 원하는 뷰만 표출이 된 상태)

* 전체 코드: https://github.com/JK0369/ExDragDropCollectionView_dragging_view