Question

I am reordering UICollectionView cells while locking few items. when i reorder unlocked items, the locked items also get rearranged. How can i shuffle array.? or i have to modify layout attributes for Elements ?

- (void)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)fromIndexPath willMoveToIndexPath:(NSIndexPath *)toIndexPath {


    PlayingCard *playingCard = [self.deck objectAtIndex:fromIndexPath.item];

    [self.deck removeObjectAtIndex:fromIndexPath.item];

    [self.deck insertObject:playingCard atIndex: toIndexPath.item];


    [collectionView performBatchUpdates:^{
        NSIndexPath *deletedItemIndexPath = [NSIndexPath indexPathForRow:fromIndexPath.row inSection:fromIndexPath.section];
        NSIndexPath *insertedItemIndexPath = [NSIndexPath indexPathForRow:newToIndexPath.row inSection:toIndexPath.section];

        [collectionView deleteItemsAtIndexPaths:@[ deletedItemIndexPath ]];
        [collectionView insertItemsAtIndexPaths:@[ insertedItemIndexPath ]];
    } completion:^(BOOL finished) {

    }];

}

- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath {
    PlayingCard *playingCard = [self.deck objectAtIndex:indexPath.item];
    return !playingCard.isLocked;
}

- (BOOL)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)fromIndexPath canMoveToIndexPath:(NSIndexPath *)toIndexPath {
    return ([self collectionView:collectionView canMoveItemAtIndexPath:fromIndexPath] &&
                    [self collectionView:collectionView canMoveItemAtIndexPath:toIndexPath]);
}

- (void)invalidateLayoutIfNecessary {
    NSIndexPath *newIndexPath = [self.collectionView indexPathForItemAtPoint:self.currentView.center];
    NSIndexPath *previousIndexPath = self.selectedItemIndexPath;

    if ((newIndexPath == nil) || [newIndexPath isEqual:previousIndexPath]) {
        return;
    }

    if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:canMoveToIndexPath:)] &&
        ![self.dataSource collectionView:self.collectionView itemAtIndexPath:previousIndexPath canMoveToIndexPath:newIndexPath]) {
        return;
    }

    self.selectedItemIndexPath = newIndexPath;

    if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:willMoveToIndexPath:)]) {
        [self.dataSource collectionView:self.collectionView itemAtIndexPath:previousIndexPath willMoveToIndexPath:newIndexPath];
    }


}

- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)gestureRecognizer {
    switch(gestureRecognizer.state) {
        case UIGestureRecognizerStateBegan: {
            NSIndexPath *currentIndexPath = [self.collectionView indexPathForItemAtPoint:[gestureRecognizer locationInView:self.collectionView]];

            if ([self.dataSource respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] &&
               ![self.dataSource collectionView:self.collectionView canMoveItemAtIndexPath:currentIndexPath]) {
                return;
            }

            self.selectedItemIndexPath = currentIndexPath;

            if ([self.delegate respondsToSelector:@selector(collectionView:layout:willBeginDraggingItemAtIndexPath:)]) {
                [self.delegate collectionView:self.collectionView layout:self willBeginDraggingItemAtIndexPath:self.selectedItemIndexPath];
            }

            UICollectionViewCell *collectionViewCell = [self.collectionView cellForItemAtIndexPath:self.selectedItemIndexPath];

            self.currentView = [[UIView alloc] initWithFrame:collectionViewCell.frame];

            collectionViewCell.highlighted = YES;
            UIImageView *highlightedImageView = [[UIImageView alloc] initWithImage:[collectionViewCell LX_rasterizedImage]];
            highlightedImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            highlightedImageView.alpha = 1.0f;

            collectionViewCell.highlighted = NO;
            UIImageView *imageView = [[UIImageView alloc] initWithImage:[collectionViewCell LX_rasterizedImage]];
            imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            imageView.alpha = 0.0f;

            [self.currentView addSubview:imageView];
            [self.currentView addSubview:highlightedImageView];
            [self.collectionView addSubview:self.currentView];

            self.currentViewCenter = self.currentView.center;

            __weak typeof(self) weakSelf = self;
            [UIView
             animateWithDuration:0.3
             delay:0.0
             options:UIViewAnimationOptionBeginFromCurrentState
             animations:^{
                 __strong typeof(self) strongSelf = weakSelf;
                 if (strongSelf) {
                     strongSelf.currentView.transform = CGAffineTransformMakeScale(1.1f, 1.1f);
                     highlightedImageView.alpha = 0.0f;
                     imageView.alpha = 1.0f;
                 }
             }
             completion:^(BOOL finished) {
                 __strong typeof(self) strongSelf = weakSelf;
                 if (strongSelf) {
                     [highlightedImageView removeFromSuperview];

                     if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didBeginDraggingItemAtIndexPath:)]) {
                         [strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didBeginDraggingItemAtIndexPath:strongSelf.selectedItemIndexPath];
                     }
                 }
             }];

            [self invalidateLayout];
        } break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded: {
            NSIndexPath *currentIndexPath = self.selectedItemIndexPath;

            if (currentIndexPath) {
                if ([self.delegate respondsToSelector:@selector(collectionView:layout:willEndDraggingItemAtIndexPath:)]) {
                    [self.delegate collectionView:self.collectionView layout:self willEndDraggingItemAtIndexPath:currentIndexPath];
                }

                self.selectedItemIndexPath = nil;
                self.currentViewCenter = CGPointZero;

                UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForItemAtIndexPath:currentIndexPath];

                __weak typeof(self) weakSelf = self;
                [UIView
                 animateWithDuration:0.3
                 delay:0.0
                 options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{
                     __strong typeof(self) strongSelf = weakSelf;
                     if (strongSelf) {
                         strongSelf.currentView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
                         strongSelf.currentView.center = layoutAttributes.center;
                     }
                 }
                 completion:^(BOOL finished) {
                     __strong typeof(self) strongSelf = weakSelf;
                     if (strongSelf) {
                         [strongSelf.currentView removeFromSuperview];
                         strongSelf.currentView = nil;
                         [strongSelf invalidateLayout];

                         if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didEndDraggingItemAtIndexPath:)]) {
                             [strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didEndDraggingItemAtIndexPath:currentIndexPath];
                         }
                     }
                 }];
            }
        } break;

        default: break;
    }
}
Was it helpful?

Solution

What you need to do is this:

When a user moves the cell you place that cell into the new index path (if the one the are replacing isn't locked).

Then with the one that has been replaced you need to move its index row by +1. This will likely need to be done in a loop and you need to check that the next cell isn't locked. if it is locked then you just increment the row by another 1. For example:

CELL 1

CELL 2 - locked

CELL 3

I move CELL 3 to CELL 1. You then need to check if CELL 2 is locked. If it is (as it is in this example) you move CELL 1 to CELL 3 instead.

//This is the card that is moving
PlayingCard *cardToMove = [self.deck objectAtIndex:fromIndexPath.row];

//This is the card that is being replaced and also needs to move.
PlayingCard *cardToReplace = [self.deck objectAtIndex:toIndexPath.row];


//We need to check if the next cell is a position which we can occupy with the cardToMove. This is where the loop will go. 
NSInteger increment = 1;

PlayingCard *cardNextToReplaced = [self.deck objectAtIndex:toIndexPath.row + increment];

while (cardNextToReplaced.isLocked) {

    increment ++;
    cardNextToReplaced == [self.deck objectAtIndex:toIndexPath.row + increment];

}

//This should now be a 'free space'
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:toIndexPath.row + increment inSection:toIndexPath.section];


//So now you just move the cardToMove to it's new index path. The cardToReplace should be moved the newly created `indexPath` above this. That should be a 'free space'.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top