最近产品出了一个需要移动UICollectionViewCell需求,其中有点小挫折,与大家分享一下。
UICollectionView移动前提条件:
iOS版本必须大于iOS 9.0
Apple官方文档,关于UICollectionView移动方法如下:
// Support for reordering
@available(iOS 9.0, *)
open func beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool // returns NO if reordering was prevented from beginning - otherwise YES
@available(iOS 9.0, *)
open func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint)
@available(iOS 9.0, *)
open func endInteractiveMovement()
@available(iOS 9.0, *)
open func cancelInteractiveMovement()
进入正文,给UICollectionView增加移动步骤如下
1. 给collectionView增加长按手势
2. 在手势识别中,设置各种移动事件
3. 在delegate设置对应cell是否可以移动
4. 在delegate中交换数据
5. 设置不可参与移动的IndexPath
具体代码如下:
import DKImagePickerController
class CommodityImageEditVC: UIViewController {
// 选取图片框架
var assets = [DKAsset]()
let commodityImageEditCellID = "CommodityImageEditCellID"
// 栏加载
lazy var gridView: UICollectionView = {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: 162.0, height: 162.0)
flowLayout.sectionInset = UIEdgeInsets(top: 20, left: 50, bottom: 20, right: 50)
flowLayout.minimumLineSpacing = 32.0
let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowLayout)
collectionView.backgroundColor = UIColor.white
collectionView.register(CommodityImageEditCell.self, forCellWithReuseIdentifier: commodityImageEditCellID)
collectionView.dataSource = self
collectionView.delegate = self
return collectionView;
}()
// MARK: - life cycle
override func viewDidLoad() {
super.viewDidLoad()
setupView()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// 设置表格视图大小
gridView.frame = CGRect(x: 0, y: 0, width: view.width, height: view.height)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - setup view
func setupView() {
view.addSubview(gridView)
setUpLongPressGesture()
}
/**
给gridView增加长按事件
*/
func setUpLongPressGesture() {
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressMoving(longPress:)))
gridView.addGestureRecognizer(longPress)
}
}
// MARK: - 长按手势识别
extension CommodityImageEditVC {
@objc func longPressMoving(longPress: UILongPressGestureRecognizer) {
// 获取长按点
let point = longPress.location(in: longPress.view)
if #available(iOS 9, *) {
switch longPress.state {
case .began:
// 根据长按点,获取对应cell的IndexPath
guard let indexPath = gridView.indexPathForItem(at: point) else {
return
}
gridView.beginInteractiveMovementForItem(at: indexPath)
case .changed:
gridView.updateInteractiveMovementTargetPosition(point)
case .ended:
gridView.endInteractiveMovement()
default:
gridView.cancelInteractiveMovement()
}
}
}
}
// MARK: - dataSource delegate
extension CommodityImageEditVC: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return assets.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: commodityImageEditCellID, for: indexPath) as? CommodityImageEditCell
if indexPath.row == assets.count {
cell?.cellType = .add
} else {
cell?.cellType = .image
cell?.updateCell(asset: assets[indexPath.row])
}
return cell!
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// 判断选中的是否为增加图片选项
guard let cell = collectionView.cellForItem(at: indexPath) as? CommodityImageEditCell else {
return
}
guard cell.cellType == .add else {
return
}
let pickerController = DKImagePickerController()
pickerController.didSelectAssets = {(assets: [DKAsset]) in
self.assets.append(contentsOf: assets)
self.gridView.reloadData()
}
present(pickerController, animated: true, completion: nil)
}
// 设置最后一个不可参与移动
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
if proposedIndexPath.item == assets.count {
return originalIndexPath
}
if originalIndexPath.item == assets.count {
return originalIndexPath
}
return proposedIndexPath
}
// 设置是否可以移动
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
if indexPath.row == assets.count {
return false
} else {
return true
}
}
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// 移动后交换数据
let moveData = assets.remove(at: sourceIndexPath.row)
assets.insert(moveData, at: destinationIndexPath.row)
}
}