最近項目中要用到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 是我進步的動力
有什麼問題可以私信我,
歡迎叨擾,
非誠勿擾 謝謝