本人iOS新手,借鉴前人经验封装了一个可拖动cell,重排cell的tableView,效果与iPhone自带天气应用中的tableView相似,可在多个section之间拖动重排,并且如果tableview内容大于屏幕,将cell拖至边缘时tableView会自动向上或向下滑动。
GitHub下载地址
效果如下:
使用方法:
- 必须实现的两个代理方法,在cell位置发生改变的时候同时更新外部数据源
/**将外部数据源数组传入,以便在移动cell数据发生改变时进行修改重排*/
- (NSArray *)originalArrayDataForTableView:(RTDragCellTableView *)tableView;
/**将修改重排后的数组传入,以便外部更新数据源*/
- (void)tableView:(RTDragCellTableView *)tableView newArrayDataForDataSource:(NSArray *)newArray;
- 可选的三个代理方法,分别是cell的三种情况
/**选中的cell准备好可以移动的时候*/
- (void)tableView:(RTDragCellTableView *)tableView cellReadyToMoveAtIndexPath:(NSIndexPath *)indexPath;
/**选中的cell正在移动,变换位置,手势尚未松开*/
- (void)cellIsMovingInTableView:(RTDragCellTableView *)tableView;
/**选中的cell完成移动,手势已松开*/
- (void)cellDidEndMovingInTableView:(RTDragCellTableView *)tableView;
基本思路:
- 拖动效果通过添加一个长按手势和对选中的cell进行截图来实现。
/**
* cell被长按手指选中,对其进行截图,原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的截图被移动到其他indexPath范围时移动隐藏的那个cell,这时一定要先更新数据源再移动cell 位置,在跨section拖动的时候如果先移动cell再更新数据源会出现崩溃。
- (void)cellRelocatedToNewIndexPath:(NSIndexPath *)indexPath{
//更新数据源并返回给外部
[self updateDataSource];
//交换移动cell位置
[self moveRowAtIndexPath:_originalIndexPath toIndexPath:indexPath];
//更新cell的原始indexPath为当前indexPath
_originalIndexPath = indexPath;
}
- 自动滚动效果的实现:在cell截图触碰顶部或底部时开启一个定时器,执行自动滚动方法
- (void)startAutoScrollTimer{
if (!_autoScrollTimer) {
_autoScrollTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(startAutoScroll)];
[_autoScrollTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
}
通过计时器不断改变tableView的contentOffset达到自动滚动效果,并且可以调节滚动速度
- (void)startAutoScroll{
CGFloat pixelSpeed = 4;
if (_autoScrollDirection == RTSnapshotMeetsEdgeTop) {//向下滚动
if (self.contentOffset.y > 0) {//向下滚动最大范围限制
[self setContentOffset:CGPointMake(0, self.contentOffset.y - pixelSpeed)];
_snapshot.center = CGPointMake(_snapshot.center.x, _snapshot.center.y - pixelSpeed);
}
}else{ //向上滚动
if (self.contentOffset.y + self.bounds.size.height < self.contentSize.height) {//向下滚动最大范围限制
[self setContentOffset:CGPointMake(0, self.contentOffset.y + pixelSpeed)];
_snapshot.center = CGPointMake(_snapshot.center.x, _snapshot.center.y + pixelSpeed);
}
}
网友评论
- (void)cellDidEndMovingInTableView:(RTDragCellTableView *)tableView;
这个可选方法为什么没有效果呢?
[self.delegate cellDidEndMovingInTableView:self];
},你看呢?