관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] UICollectionView에서 원하는 뷰 영역만 드래그 할 때 보이도록 하는 방법 (itemsForBeginning, dragInteractionEnabled, dragDelegate, dropDelegate) 본문

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, Drop UI

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

 

Comments