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的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 拖放单元格

UICollectionView 快速拖放

在两个 UICollectionView 之间拖放

在具有 UITableView 的 UICollectionView 中拖放

UICollectionView 与 SwiftUI + 拖放重新排序可能吗?

如何在 UICollectionView 拖放期间删除“幽灵”单元格,并使移动单元格不透明?