寫(xiě)在前面
- 最近不忙丽声,看見(jiàn)一個(gè)好玩酣衷,而且很實(shí)用千元,既然閑來(lái)無(wú)事罚拟,就自己動(dòng)手做出來(lái)驱敲,coder. 感覺(jué)還不錯(cuò)就是界面比較丑陋了點(diǎn)宽闲,不過(guò)沒(méi)關(guān)系明白原理就好了便锨!愛(ài)生活,愛(ài)鉆研姚建,愛(ài)分享
- github 地址https://github.com/zyjian/EditCollectionViewCell
- 記得留下你的腳印哦
進(jìn)入主題
-
首先我們還是先看看效果吧
QQ20180316-183625.gif
需求分析
- 類(lèi)似今日頭條首頁(yè)的橫向菜單掸冤,編輯稿湿,移動(dòng)刪除押赊,都是可以的,這里我們做的是移動(dòng)罗丰,刪除也是同樣的道理
- 步驟拆解: 給每個(gè)cell 添加長(zhǎng)按手勢(shì)再姑,長(zhǎng)按進(jìn)入編輯狀態(tài)元镀,此時(shí)可以拖動(dòng)當(dāng)前cell 移動(dòng)到想要調(diào)整的位置。
原理分析
- 主要是UIcollectionView 的一個(gè)方法的靈活使用:collectionView.moveItem(at: indexPathP, to: nextIndexPathP)
- 創(chuàng)建collectionView 并且構(gòu)造數(shù)據(jù)源,這里是用的懶加載讨永,注意這里我們使用的OC 的NSMutableArray蔽挠,因?yàn)槲覀円褂胑xchange方法這樣更簡(jiǎn)單
private var dataArray:NSMutableArray = {
var array:NSMutableArray = NSMutableArray.init()
for i in 0..<100 {
array.add("第\(i)個(gè)")
}
return array
}()
- 給cell 添加長(zhǎng)按手勢(shì)澳淑,并且將手勢(shì)事件通過(guò)代理協(xié)議插佛,傳到viewController中
- 核心代碼
extension ViewController:ItemCVCProtocl {
func itemCVClongPress(long: UILongPressGestureRecognizer) {
let cell:ItemCVC = long.view as! ItemCVC
if long.state == .began {//長(zhǎng)按開(kāi)始
//獲取截圖cell
snapshotView = cell.snapshotView(afterScreenUpdates: true)!
snapshotView?.center = cell.center
collectionView.addSubview(snapshotView!)
indexPathP = collectionView.indexPath(for: cell)!
originalCell = cell
originalCell.isHidden = true
startPoint = long.location(in: collectionView)
//colllectionViewAnimateCell(isgo: true)
}else if(long.state == .changed){
//移動(dòng)
let tranx : CGFloat = long.location(ofTouch: 0, in: collectionView).x - startPoint.x
let trany : CGFloat = long.location(ofTouch: 0, in: collectionView).y - startPoint.y
snapshotView?.center = __CGPointApplyAffineTransform((snapshotView?.center)!, CGAffineTransform.init(translationX: tranx, y: trany))
//更新最新的開(kāi)始移動(dòng)
startPoint = long.location(ofTouch: 0, in: collectionView)
//計(jì)算截圖和那個(gè)cell 交換
for cell in collectionView.visibleCells {
//跳過(guò)自己本身那個(gè)cell
if collectionView.indexPath(for: cell) == indexPathP {
continue;
}
//計(jì)算中心距
let space:CGFloat = sqrt(pow(snapshotView!.center.y-cell.center.y,2)+pow(snapshotView!.center.x-cell.center.x,2))
//如果相交一半且兩個(gè)視圖Y的絕對(duì)值小于高度的一半就移動(dòng)
if space <= snapshotView!.bounds.width * 0.5
&& (fabs(snapshotView!.center.y - cell.center.y) <= snapshotView!.bounds.height * 0.5) {
nextIndexPathP = collectionView.indexPath(for: cell)!
if nextIndexPathP.item > indexPathP.item {
for i in indexPathP.item..<nextIndexPathP.item {
self.dataArray.exchangeObject(at: i, withObjectAt: i+1)
}
}else{
for i in (nextIndexPathP.item ..< indexPathP.item).reversed() {
self.dataArray.exchangeObject(at: i, withObjectAt: i - 1)
}
}
//移動(dòng)
collectionView.moveItem(at: indexPathP, to: nextIndexPathP)
indexPathP = nextIndexPathP;
break;
}
}
}else if long.state == .ended {
snapshotView?.removeFromSuperview()
originalCell.isHidden = false
//colllectionViewAnimateCell(isgo: false)
}
}
}
- 注意:
- snapshotView = cell.snapshotView(afterScreenUpdates: true)! 截圖這里是獲取一個(gè)cell 副本氢拥,是兩個(gè)不同的對(duì)象
//移動(dòng)
let tranx : CGFloat = long.location(ofTouch: 0, in: collectionView).x - startPoint.x
let trany : CGFloat = long.location(ofTouch: 0, in: collectionView).y - startPoint.y
snapshotView?.center = __CGPointApplyAffineTransform((snapshotView?.center)!, CGAffineTransform.init(translationX: tranx, y: trany))
這里的 __CGPointApplyAffineTransform 創(chuàng)建一個(gè)平移的變化
__CGPointApplyAffineTransform((snapshotView?.center)!, CGAffineTransform.init(translationX: tranx, y: trany))
意思是相對(duì)于snapshotView?.center 這個(gè)點(diǎn)平移 X: tranx, y: trany嫩海,返回值是一個(gè)CGPoint
- 遍歷collectionView中的cell(長(zhǎng)按那個(gè)cell本身除外)叁怪, 是否需要交換位置奕谭。
需要移動(dòng)的條件
3.1 計(jì)算中心距 3.2 相交小于一半的時(shí)候
結(jié)尾寄語(yǔ)
藝術(shù)-海.png
如果你覺(jué)得不清晰的話痴荐,歡迎留言,互相學(xué)習(xí)共同進(jìn)步难捌!
最后再提醒一句文中的demo 在guhub地址是* github 地址https://github.com/zyjian/EditCollectionViewCell