UICollectionView 拖放更新所有受影响的 indexPaths
Posted
技术标签:
【中文标题】UICollectionView 拖放更新所有受影响的 indexPaths【英文标题】:UICollectionView Drag and Drop update all affected indexPaths 【发布时间】:2014-05-27 10:27:55 【问题描述】:我有一个UICollectionView
,它使用拖放功能对单元格进行手动重新排序。
我只有 1 个部分,其中包含两列大小相同的单元格。
为了正确解释我的问题,我需要上传屏幕截图,但我没有足够的代表,所以我必须用数字来解释。
1 2 3 4 5 6
这表示一个CollectionView
,其中 2 列中的 6 个单元格填满了整个屏幕。
所以我遇到的问题是,例如,如果我交换单元格 3 和单元格 2 一切正常,因为单元格 3 变为单元格 2,反之亦然,当我交换单元格 3 和单元格 1 时会出现问题,因为单元格 3 变为单元格1 和单元格1 变成单元格2 和单元格2 变成单元格3。
现在它重新排列,但一旦应用程序调用[self.collectionView reloadData];
cell3 将保持在我丢弃它的位置 1,但新的单元格 2 和 3 将交换位置,就好像索引没有更新一样。
长按手势可在拖动时处理单元格的删除和插入(单元格快照),并且所有图块会重新排列并正确放入各个部分。
-(IBAction)longPressGestureRecognized:(id)sender
UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
UIGestureRecognizerState state = longPress.state;
CGPoint location = [longPress locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:location];
static UIView *snapshot = nil;
static NSIndexPath *sourceIndexPath = nil;
switch (state)
case UIGestureRecognizerStateBegan:
if (indexPath)
sourceIndexPath = indexPath;
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
snapshot = [self customSnapshotFromView:(cell)];
__block CGPoint center = cell.center;
snapshot.center = center;
snapshot.alpha = 0.98;
[self.collectionView 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.hidden = YES;
completion:nil];
break;
case UIGestureRecognizerStateChanged:
CGPoint center = snapshot.center;
center.y = location.y;
center.x = location.x;
snapshot.center = center;
if (indexPath && ![indexPath isEqual:sourceIndexPath])
[people2 exchangeObjectAtIndex:indexPath.item withObjectAtIndex:sourceIndexPath.item];
[self.collectionView moveItemAtIndexPath:sourceIndexPath toIndexPath:indexPath];
sourceIndexPath = indexPath;
[databaseClass arrangeData:people2];
break;
default:
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:sourceIndexPath];
[UIView animateWithDuration:0.25 animations:^
snapshot.center = cell.center;
snapshot.transform = CGAffineTransformIdentity;
snapshot.alpha = 0.0;
cell.hidden = NO;
completion:^(BOOL finished)
[snapshot removeFromSuperview];
snapshot = nil;
];
sourceIndexPath = nil;
break;
我正在使用 sqlite 方法将图块的排列存储在数据库中。
+(void)arrangeData:(NSArray*)arrange
[self databaseInit];
if (sqlite3_open(dbpath, &peopleDB ) == SQLITE_OK)
for (int i = 0; i < [arrange count]; i++)
NSString *insertSQL = [NSString stringWithFormat:@"UPDATE PEOPLE SET ARRANGE = %i WHERE ID = %i",i+1,[[arrange objectAtIndex:i] ID]];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2( peopleDB, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
NSLog(@"Arranged Successfully");
else
NSLog(@"%s SQLITE_ERROR '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(peopleDB), sqlite3_errcode(peopleDB));
sqlite3_finalize(statement);
sqlite3_close(peopleDB);
这并不重要,但快照很重要:
-(UIView *)customSnapshotFromView:(UIView *)inputView
UIView *snapshot = [inputView snapshotViewAfterScreenUpdates:YES];
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;
如果有人对如何让细胞在长按结束时保持原位有任何想法,我将不胜感激。
【问题讨论】:
【参考方案1】:我不懂sqlite,但是按照你说的,好像是交换数据而不是移动相关数据。
在您的示例中,您必须从它的数组中删除 dataForCell3,然后将其插入到 dataForCell1 的索引处。 似乎不是您交换了 dataForCell3 和 dataForCell1。
【讨论】:
我刚刚拿起了这个。感谢您指出这一点。如果我修复了会通知你以上是关于UICollectionView 拖放更新所有受影响的 indexPaths的主要内容,如果未能解决你的问题,请参考以下文章
在具有 UITableView 的 UICollectionView 中拖放