我在集合视图中有单元格。这些细胞中的一些可能比其他细胞大。我计算collectionView(_:layout:sizeForItemAt:)
中单元格的大小。
为了启用在集合视图中的拖动,我覆盖了collectionView(_:canMoveItemAt:)
和collectionView(_:moveItemAt:to:)
。到目前为止,可以拖动单元格。
我有一个交换数据源中项目的功能:
func moveCell<T>(from source: IndexPath, to destination: IndexPath, in dataSource: inout [[T]]) {
let itemToMove = dataSource[source.section][source.row]
dataSource[source.section].remove(at: source.row)
dataSource[destination.section].insert(itemToMove, at: destination.row)
}
最初,我在moveCell(from:to:in:)
方法中实现了collectionView(_:moveItemAt:to:)
函数。 但是,使用此解决方案时,单元的大小变得混乱了。另外,如果我尝试将单元格拖动到另一部分,则会在collectionView(_:layout:sizeForItemAt:)
方法中超出索引范围。
因此,我尝试将moveCell(from:to:in:)
函数放在collectionView(_:targetIndexPathForMoveFromItemAt:toProposedIndexPath:)
中,然后将collectionView(_:moveItemAt:to:)
方法留空。 (这不是最佳选择,但是无论如何都需要这样做...)因此,在这种情况下,单元格的大小对于我要拖动的单元格以及所有其他单元格都是正确的。 但是,如果我将第一部分的最后一个单元格或最后一个部分的第一个单元格拖到另一个部分中,则会在collectionView(_:layout:sizeForItemAt:)
方法中得到索引超出范围的错误。
这是我的数据源:
var data: [[String]] = [
["Rabbit", "Turtle", "Unecessarily long title for getting a second line maybe hopefully."],
["Fish"]
]
尺寸计算:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.contentSize.width
let height: CGFloat = data[indexPath.section][indexPath.row].height(with: width, size: 17) + 20
return CGSize(width: width, height: height)
}
在我描述的第一个解决方案中,我实现了这样的移动:
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
moveCell(from: sourceIndexPath, to: destinationIndexPath, in: &data)
}
在我描述的第二个解决方案中,我实现了这样的移动:
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// moveCell(from: sourceIndexPath, to: destinationIndexPath, in: &data)
}
override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
moveCell(from: originalIndexPath, to: proposedIndexPath, in: &data)
return proposedIndexPath
}
Here is my full UICollectionViewController code for my first solution.