自定义拖放UICollectionViewLayout捕捉到网格

时间:2018-03-03 10:41:10

标签: swift drag-and-drop uicollectionview uicollectionviewlayout custom-view

我正在开发一个应用程序,我可以跟踪我的青少年足球队的替换。

按照Payal Gupta关于阻力&放入收藏品我设法在两个集合视图(PlayersOntoTheField和Substitutes)之间拖放工作Screenshot

当我将替代玩家拖入我的游乐场时,它现在应该捕捉到预定义的团队阵容(例如截屏中的3-2-1)。是否可以使用自定义UICollectionViewLayout获取此类行为,或者是否有人有其他建议?

非常感谢您提前寻求帮助。

丹尼

//Based on a work by: 
//Payal Gupta (https://github.com/pgpt10/DragAndDrop-CollectionView)

import UIKit

class ViewController: UIViewController
{
    private var substitutes = ["player1", "player2", "player3", "player4"]
    private var players = [String]()

    @IBOutlet weak var substitutesCollectionView: UICollectionView!
    @IBOutlet weak var playersCollectionView: UICollectionView!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        //SubstitutesCollectionView drag and drop configuration
        self.substitutesCollectionView.dragInteractionEnabled = true
        self.substitutesCollectionView.dragDelegate = self
        self.substitutesCollectionView.dropDelegate = self

        //PlayersCollectionView drag and drop configuration
        self.playersCollectionView.dragInteractionEnabled = true
        self.playersCollectionView.dropDelegate = self
        self.playersCollectionView.dragDelegate = self
        self.playersCollectionView.reorderingCadence = .fast //default value - .immediate
    }

    //MARK: Private Methods
    private func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView)
    {
        let items = coordinator.items
        if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath
        {
            var dIndexPath = destinationIndexPath
            if dIndexPath.row >= collectionView.numberOfItems(inSection: 0)
            {
                dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1
            }
            collectionView.performBatchUpdates({
                if collectionView === self.playersCollectionView
                {
                    self.players.remove(at: sourceIndexPath.row)
                    self.players.insert(item.dragItem.localObject as! String, at: dIndexPath.row)
                }
                else
                {
                    self.substitutes.remove(at: sourceIndexPath.row)
                    self.substitutes.insert(item.dragItem.localObject as! String, at: dIndexPath.row)
                }
                collectionView.deleteItems(at: [sourceIndexPath])
                collectionView.insertItems(at: [dIndexPath])
            })
            coordinator.drop(items.first!.dragItem, toItemAt: dIndexPath)
        }
    }

    private func copyItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView)
    {
        collectionView.performBatchUpdates({
            var indexPaths = [IndexPath]()
            for (index, item) in coordinator.items.enumerated()
            {
                let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section)
                if collectionView === self.playersCollectionView
                {
                    self.players.insert(item.dragItem.localObject as! String, at: indexPath.row)
                }
                else
                {
                    self.substitutes.insert(item.dragItem.localObject as! String, at: indexPath.row)
                }
                indexPaths.append(indexPath)
            }
            collectionView.insertItems(at: indexPaths)
        })
    }
}

// MARK: - UICollectionViewDataSource Methods
extension ViewController : UICollectionViewDataSource
{
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        return collectionView == self.substitutesCollectionView ? self.substitutes.count : self.players.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        if collectionView == self.substitutesCollectionView
        {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath) as! MyCollectionViewCell
            cell.customImageView?.image = UIImage(named: self.substitutes[indexPath.row])
            cell.customLabel.text = self.substitutes[indexPath.row].capitalized
            return cell
        }
        else
        {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath) as! MyCollectionViewCell
            cell.customImageView?.image = UIImage(named: self.players[indexPath.row])
            cell.customLabel.text = self.players[indexPath.row].capitalized
            return cell
        }
    }
}

// MARK: - UICollectionViewDragDelegate Methods
extension ViewController : UICollectionViewDragDelegate
{
    func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]
    {
        let item = collectionView == substitutesCollectionView ? self.substitutes[indexPath.row] : self.players[indexPath.row]
        let itemProvider = NSItemProvider(object: item as NSString)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        dragItem.localObject = item
        return [dragItem]
    }

    func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem]
    {
        let item = collectionView == substitutesCollectionView ? self.substitutes[indexPath.row] : self.players[indexPath.row]
        let itemProvider = NSItemProvider(object: item as NSString)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        dragItem.localObject = item
        return [dragItem]
    }

    func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters?
    {
        if collectionView == substitutesCollectionView
        {
            let previewParameters = UIDragPreviewParameters()
            previewParameters.visiblePath = UIBezierPath(rect: CGRect(x: 15, y: 5, width: 30, height: 30))
            return previewParameters
        }
        return nil
    }
}

// MARK: - UICollectionViewDropDelegate Methods
extension ViewController : UICollectionViewDropDelegate
{
    func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool
    {
        return session.canLoadObjects(ofClass: NSString.self)
    }

    func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal
    {
        if collectionView === self.substitutesCollectionView
        {
            if collectionView.hasActiveDrag
            {
                return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
            }
            else
            {
                return UICollectionViewDropProposal(operation: .forbidden)
            }
        }
        else
        {
            if collectionView.hasActiveDrag
            {
                return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
            }
            else
            {
                return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath)
            }
        }
    }

    func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator)
    {
        let destinationIndexPath: IndexPath
        if let indexPath = coordinator.destinationIndexPath
        {
            destinationIndexPath = indexPath
        }
        else
        {
            // Get last index path of table view.
            let section = collectionView.numberOfSections - 1
            let row = collectionView.numberOfItems(inSection: section)
            destinationIndexPath = IndexPath(row: row, section: section)
        }

        switch coordinator.proposal.operation
        {
        case .move:
            self.reorderItems(coordinator: coordinator, destinationIndexPath:destinationIndexPath, collectionView: collectionView)
            break

        case .copy:
            self.copyItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)

        default:
            return
        }
    }
}

1 个答案:

答案 0 :(得分:0)

到目前为止我的自定义UICollectionViewLayout的解决方法:

r.get(1); r.get(2);