最近项目中要用到tableview 插入 删除 移动的功能,以前开发的时候没用到这类的工能,基本上时从零开始,期间遇到不少坑
下面我们一步一步来看看这个功能怎么实现的
1,插入功能 简单 刚开始 初始化一个数据源的可变数组,在点击添加内容按钮的时候 在点击事件里面为数据源数组添加数据然后你可以relodata 然后功能就实现啦
if (sender.tag==501) {
NSMutableDictionary *tempDict = [NSMutableDictionary dictionary];
[tempDict setObject:@"0" forKey:@"type"];
[self.dataSouce addObject:tempDict];
[self.data_souce addObject:tempDict];
[comTableView reloadData];
NSLog(@"昂起值%@",self.dataSouce);
}
因为我点击点击添加按钮的时候的 是分添加文字或者图片俩种,所以我在给数据源添加了一个字典进去,type值 就是分开哪个是文本哪个是图片,
在reloadData的时候 你会遇到复用问题,这里就不阐述 复用的概念啦,就是你在reloaddata的时候 你添加到文本上的内容没了,或者你添加的多张图片瞬间变成同一张了,
解决的办法是,你把添加的文本或者图片存放到字典里然后把刚开始存储在数组中的字典覆盖掉,然后在reloadData的时候把存好的内容在重新赋值回去,cellForRowAtIndexPath里这样写
NSDictionary *dict = self.dataSouce[indexPath.row];
if ([dict[@"type"]isEqualToString:@"0"]) {
self.cell.comImage.hidden = YES;
CreateWeakSelf;
self.cell.textViewInputCompletion = ^(NSString *text){
NSMutableDictionary *temp=[[NSMutableDictionary alloc]init];
[temp setObject:@"0" forKey:@"type"];
[temp setObject:text forKey:@"str"];
[weakSelf.dataSouce replaceObjectAtIndex:indexPath.row withObject:temp];
[weakSelf.data_souce replaceObjectAtIndex:indexPath.row withObject:temp];
};
self.cell.comTextView.text =[dict objectForKey:@"str"];
2,删除
这个比较简单 就是删除你原来数据源数组里面先对应的index就行,
-(void)delegateAction:(UIButton *)sender{
NSLog(@"index的值为%@",sender.additionalMark);
NSString *str = [NSString stringWithFormat:@"%@",sender.additionalMark];
NSInteger i = [str integerValue];
// NSUInteger i= sender.additionalMark;
[self.dataSouce removeObjectAtIndex:i];
[self.data_souce removeObjectAtIndex:i];
[comTableView reloadData];
}
这里我遇到的问题是,刚开始我是初始化一个 NSIndexpath 然后 在cellforrowindexptath里面 把indexpath赋值给我初始化的NSIndexpath 拿indexpate.row作为删除的数组里index下标的,问题是当你在reloadData的时候,赋值给NSindexpath 永远是最下面cell,所以后来解决办法是 当你点击删除按钮的时候 把当前要铲除cell的 indexpath 赋值,然后问题就解决啦
self. cell.deleageBtn.additionalMark = [NSString stringWithFormat:@"%ld",indexPath.row];
3,移动
我是直接百度的,具体的没有去深研究,大概就是 给当前的cell添加长按手势,当你触发手势的时候,会把当前的cell进行一个快照,说白了就是你拖到的不是实际的cell,而是照片,当你拖动的时候,然后再把数据源的中的数据进行重新排序,然后在reloadta一下 就ok啦 我把代码直接粘贴吧
#pragma mark 创建cell的快照
- (UIView *)customSnapshoFromView:(UIView *)inputView {
// 用cell的图层生成UIImage,方便一会显示
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, NO, 0);
[inputView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// 自定义这个快照的样子(下面的一些参数可以自己随意设置)
UIView *snapshot = [[UIImageView alloc] initWithImage:image];
snapshot.layer.masksToBounds = NO;
snapshot.layer.cornerRadius = 0.0;
snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);
snapshot.layer.shadowRadius = 5.0;
snapshot.layer.shadowOpacity = 0.4;
return snapshot;
}
#pragma mark 长按手势方法
- (void)longPressGestureRecognized:(id)sender {
UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
UIGestureRecognizerState state = longPress.state;
CGPoint location = [longPress locationInView:comTableView];
NSIndexPath *indexPath = [comTableView indexPathForRowAtPoint:location];
static UIView *snapshot = nil;
switch (state) {
// 已经开始按下
case UIGestureRecognizerStateBegan: {
// 判断是不是按在了cell上面
if (indexPath) {
sourceIndexPath = indexPath;
UITableViewCell *cell = [comTableView cellForRowAtIndexPath:indexPath];
// 为拖动的cell添加一个快照
snapshot = [self customSnapshoFromView:cell];
// 添加快照至tableView中
__block CGPoint center = cell.center;
snapshot.center = center;
snapshot.alpha = 0.0;
[comTableView addSubview:snapshot];
// 按下的瞬间执行动画
[UIView animateWithDuration:0.25 animations:^{
center.y = location.y;
snapshot.center = center;
snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
snapshot.alpha = 0.98;
cell.alpha = 0.0;
} completion:^(BOOL finished) {
cell.hidden = YES;
}];
}
break;
}
// 移动过程中
case UIGestureRecognizerStateChanged: {
// 这里保持数组里面只有最新的两次触摸点的坐标
[self.touchPoints addObject:[NSValue valueWithCGPoint:location]];
if (self.touchPoints.count > 2) {
[self.touchPoints removeObjectAtIndex:0];
}
CGPoint center = snapshot.center;
// 快照随触摸点y值移动(当然也可以根据触摸点的y轴移动量来移动)
center.y = location.y;
// 快照随触摸点x值改变量移动
CGPoint Ppoint = [[self.touchPoints firstObject] CGPointValue];
CGPoint Npoint = [[self.touchPoints lastObject] CGPointValue];
CGFloat moveX = Npoint.x - Ppoint.x;
center.x += moveX;
snapshot.center = center;
NSLog(@"%@---%f----%@", self.touchPoints, moveX, NSStringFromCGPoint(center));
NSLog(@"%@", NSStringFromCGRect(snapshot.frame));
// 是否移动了
if (indexPath && ![indexPath isEqual:sourceIndexPath]) {
// 更新数组中的内容
[self.dataSouce exchangeObjectAtIndex:
indexPath.row withObjectAtIndex:sourceIndexPath.row];
// 把cell移动至指定行
[comTableView moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];
// 存储改变后indexPath的值,以便下次比较
sourceIndexPath = indexPath;
}
break;
}
// 长按手势取消状态
default: {
// 清除操作
// 清空数组,非常重要,不然会发生坐标突变!
[self.touchPoints removeAllObjects];
[comTableView reloadData];
UITableViewCell *cell = [comTableView cellForRowAtIndexPath:sourceIndexPath];
cell.hidden = NO;
cell.alpha = 0.0;
// 将快照恢复到初始状态
[UIView animateWithDuration:0.25 animations:^{
snapshot.center = cell.center;
snapshot.transform = CGAffineTransformIdentity;
snapshot.alpha = 0.0;
cell.alpha = 1.0;
} completion:^(BOOL finished) {
sourceIndexPath = nil;
[snapshot removeFromSuperview];
snapshot = nil;
[comTableView reloadData];
}];
break;
}
}
}
大概功能差不多已经实现,不过实际开发的时候,还会有许多问题需要考虑,比如修改文本内容的时候,你要实时更新数据源中的内容,返回到上一个界面的时候,在重新进入的时候,你还需要tableview展示你刚才添加的内容以便修改,,,,,期间我遇到的问题很多,还有很多细节问题,我就不一一阐述啦 如果开发中你们需要这样的功能,遇到什么问题可以私信给我,尽力帮助你们
最后附上demo
github下载地址
不麻烦的话可以 给个 star
你们的star 是我进步的动力
有什么问题可以私信我,
欢迎叨扰,
非诚勿扰 谢谢
网友评论