0

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;
    }
}
Umair Suraj
  • 480
  • 11
  • 22
  • what do you mean by disturbed ? – CW0007007 Apr 28 '14 at 09:59
  • Could you please help me now? – Umair Suraj Apr 28 '14 at 10:17
  • So if you move a cell in front of a locked cell what do you expect to happen ? The locked cell is obviously going to move as well as you can't have two cells in the same place... – CW0007007 Apr 28 '14 at 10:26
  • if i move cell in front of a locked cell, i have check for it whether its possible to move from "fromIndexPath" to "toIndexPath". If element on toIndexPath is locked it will return zero. – Umair Suraj Apr 28 '14 at 10:37
  • lets suppose. i have 3 items. middle one is locked only. i drag 3rd item on first item. first item should go to position of 3rd element not on 2nd item position. i donot want replacement of 3rd item with first item. – Umair Suraj Apr 28 '14 at 10:40
  • This is contradictory: first item should go to position of 3rd element not on 2nd item position. i donot want replacement of 3rd item with first item. – CW0007007 Apr 28 '14 at 10:41
  • How are you currently re-ordering the cells ? Code ? – CW0007007 Apr 28 '14 at 10:42
  • 2nd item is locked one. i donot want its rearrangement. – Umair Suraj Apr 28 '14 at 10:42
  • i have an idea that i can check if toIndexPath.row+1 has item locked then shift item one more position. But how can i implement this idea.? – Umair Suraj Apr 28 '14 at 10:43
  • i am using library LXReorderableCollectionViewFlowLayout. – Umair Suraj Apr 28 '14 at 10:45

1 Answers1

1

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'.
CW0007007
  • 5,681
  • 4
  • 26
  • 31