拖放CollectionView
为 Swift 4.0 编写,实现跨多个 UICollectionView 的拖放数据。
在 Appetize.io 上试一试:Appetize.io!
要求
- iOS 8.0+
- XCode 9.0+
- Swift 4.0+
安装
Cocoa Pods
pod 'KDDragAndDropCollectionViews', '~> 1.5.2'
手动安装
将 Classes/
目录中的文件添加到项目中。
快速指南
将UICollectionView设置为
然后设置一个类作为dataSource并实现
class ViewController: UIViewController, KDDragAndDropCollectionViewDataSource {
@IBOutlet weak var firstCollectionView: KDDragAndDropCollectionView!
@IBOutlet weak var secondCollectionView: KDDragAndDropCollectionView!
@IBOutlet weak var thirdCollectionView: KDDragAndDropCollectionView!
var data : [[DataItem]] = [[DataItem]]() // just for this example
var dragAndDropManager : KDDragAndDropManager?
override func viewDidLoad() {
let all = [firstCollectionView, secondCollectionView, thirdCollectionView]
self.dragAndDropManager = KDDragAndDropManager(canvas: self.view, collectionViews: all)
}
}
用户代码的唯一责任是管理代表收集视图单元格的数据。收集视图的数据源必须实现
在示例中,我们使用了3个具有各自标签的UICollectionView(我知道这是不好的实践,但只是示例...),以及包含3个数组的数组数据。在这种情况下,上述实现的示例可能是
func collectionView(collectionView: UICollectionView, dataItemForIndexPath indexPath: NSIndexPath) -> AnyObject {
return data[collectionView.tag][indexPath.item]
}
func collectionView(collectionView: UICollectionView, insertDataItem dataItem : AnyObject, atIndexPath indexPath: NSIndexPath) -> Void {
if let di = dataItem as? DataItem {
data[collectionView.tag].insert(di, atIndex: indexPath.item)
}
}
func collectionView(collectionView: UICollectionView, deleteDataItemAtIndexPath indexPath : NSIndexPath) -> Void {
data[collectionView.tag].removeAtIndex(indexPath.item)
}
func collectionView(collectionView: UICollectionView, moveDataItemFromIndexPath from: NSIndexPath, toIndexPath to : NSIndexPath) -> Void {
let fromDataItem: DataItem = data[collectionView.tag][from.item]
data[collectionView.tag].removeAtIndex(from.item)
data[collectionView.tag].insert(fromDataItem, atIndex: to.item)
}
func collectionView(_ collectionView: UICollectionView, indexPathForDataItem dataItem: AnyObject) -> IndexPath? {
guard let candidate = dataItem as? DataItem else { return nil }
for (i,item) in data[collectionView.tag].enumerated() {
if candidate != item { continue }
return IndexPath(item: i, section: 0)
}
return nil
}
高级使用
防止特定项目被拖动和/或丢弃
对于更精细地调整哪些项目可以拖动以及哪些不能拖动,我们可以实现来自
func collectionView(_ collectionView: UICollectionView, cellIsDraggableAtIndexPath indexPath: IndexPath) -> Bool {
return indexPath.row % 2 == 0
}
数据项和Equatable
在项目中包含的示例代码中,我创建了一个
class DataItem : Equatable {
var indexes: String
var colour: UIColor
init(indexes: String, colour: UIColor = UIColor.clear) {
self.indexes = indexes
self.colour = colour
}
static func ==(lhs: DataItem, rhs: DataItem) -> Bool {
return lhs.indexes == rhs.indexes && lhs.colour == rhs.colour
}
}
在开发过程中,您将创建自己的类型,这些类型必须遵守上述