本人iOS新手跪帝,借鑒前人經(jīng)驗(yàn)封裝了一個(gè)可拖動(dòng)cell,重排cell的tableView锨并,效果與iPhone自帶天氣應(yīng)用中的tableView相似桦锄,可在多個(gè)section之間拖動(dòng)重排,并且如果tableview內(nèi)容大于屏幕抠忘,將cell拖至邊緣時(shí)tableView會(huì)自動(dòng)向上或向下滑動(dòng)撩炊。
GitHub下載地址
效果如下:
使用方法:
- 必須實(shí)現(xiàn)的兩個(gè)代理方法,在cell位置發(fā)生改變的時(shí)候同時(shí)更新外部數(shù)據(jù)源
/**將外部數(shù)據(jù)源數(shù)組傳入褐桌,以便在移動(dòng)cell數(shù)據(jù)發(fā)生改變時(shí)進(jìn)行修改重排*/
- (NSArray *)originalArrayDataForTableView:(RTDragCellTableView *)tableView;
/**將修改重排后的數(shù)組傳入衰抑,以便外部更新數(shù)據(jù)源*/
- (void)tableView:(RTDragCellTableView *)tableView newArrayDataForDataSource:(NSArray *)newArray;
- 可選的三個(gè)代理方法,分別是cell的三種情況
/**選中的cell準(zhǔn)備好可以移動(dòng)的時(shí)候*/
- (void)tableView:(RTDragCellTableView *)tableView cellReadyToMoveAtIndexPath:(NSIndexPath *)indexPath;
/**選中的cell正在移動(dòng)荧嵌,變換位置呛踊,手勢(shì)尚未松開*/
- (void)cellIsMovingInTableView:(RTDragCellTableView *)tableView;
/**選中的cell完成移動(dòng)砾淌,手勢(shì)已松開*/
- (void)cellDidEndMovingInTableView:(RTDragCellTableView *)tableView;
基本思路:
- 拖動(dòng)效果通過添加一個(gè)長按手勢(shì)和對(duì)選中的cell進(jìn)行截圖來實(shí)現(xiàn)。
/**
* cell被長按手指選中谭网,對(duì)其進(jìn)行截圖汪厨,原cell隱藏
*/
- (void)cellSelectedAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath];
UIView *snapshot = [self customSnapshotFromView:cell];
[self addSubview:snapshot];
_snapshot = snapshot;
cell.hidden = YES;
CGPoint center = _snapshot.center;
center.y = _fingerLocation.y;
[UIView animateWithDuration:0.2 animations:^{
_snapshot.transform = CGAffineTransformMakeScale(1.03, 1.03);
_snapshot.alpha = 0.98;
_snapshot.center = center;
}];
}
- 在cell的截圖被移動(dòng)到其他indexPath范圍時(shí)移動(dòng)隱藏的那個(gè)cell,這時(shí)一定要先更新數(shù)據(jù)源再移動(dòng)cell 位置愉择,在跨section拖動(dòng)的時(shí)候如果先移動(dòng)cell再更新數(shù)據(jù)源會(huì)出現(xiàn)崩潰劫乱。
- (void)cellRelocatedToNewIndexPath:(NSIndexPath *)indexPath{
//更新數(shù)據(jù)源并返回給外部
[self updateDataSource];
//交換移動(dòng)cell位置
[self moveRowAtIndexPath:_originalIndexPath toIndexPath:indexPath];
//更新cell的原始indexPath為當(dāng)前indexPath
_originalIndexPath = indexPath;
}
- 自動(dòng)滾動(dòng)效果的實(shí)現(xiàn):在cell截圖觸碰頂部或底部時(shí)開啟一個(gè)定時(shí)器,執(zhí)行自動(dòng)滾動(dòng)方法
- (void)startAutoScrollTimer{
if (!_autoScrollTimer) {
_autoScrollTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(startAutoScroll)];
[_autoScrollTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
}
通過計(jì)時(shí)器不斷改變tableView的contentOffset達(dá)到自動(dòng)滾動(dòng)效果锥涕,并且可以調(diào)節(jié)滾動(dòng)速度
- (void)startAutoScroll{
CGFloat pixelSpeed = 4;
if (_autoScrollDirection == RTSnapshotMeetsEdgeTop) {//向下滾動(dòng)
if (self.contentOffset.y > 0) {//向下滾動(dòng)最大范圍限制
[self setContentOffset:CGPointMake(0, self.contentOffset.y - pixelSpeed)];
_snapshot.center = CGPointMake(_snapshot.center.x, _snapshot.center.y - pixelSpeed);
}
}else{ //向上滾動(dòng)
if (self.contentOffset.y + self.bounds.size.height < self.contentSize.height) {//向下滾動(dòng)最大范圍限制
[self setContentOffset:CGPointMake(0, self.contentOffset.y + pixelSpeed)];
_snapshot.center = CGPointMake(_snapshot.center.x, _snapshot.center.y + pixelSpeed);
}
}