如何在锁定其中一些单元格时重新排序 UICollectionView 单元格
Posted
技术标签:
【中文标题】如何在锁定其中一些单元格时重新排序 UICollectionView 单元格【英文标题】:How to reorder UICollectionView cells while locks some of them 【发布时间】:2014-04-28 09:30:27 【问题描述】:我正在重新排序UICollectionView
单元格,同时锁定了几个项目。当我重新排序未锁定的项目时,锁定的项目也会重新排列。我怎样才能洗牌阵列。?或者我必须修改元素的布局属性?
- (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;
【问题讨论】:
不安是什么意思? 现在能帮帮我吗? 那么,如果您将一个单元格移动到一个锁定的单元格前面,您期望会发生什么?锁定的牢房显然会移动,而且你不能在同一个地方有两个牢房...... 如果我将单元格移动到锁定单元格的前面,我会检查它是否可以从“fromIndexPath”移动到“toIndexPath”。如果 toIndexPath 上的元素被锁定,它将返回零。 让我们假设。我有 3 件物品。仅中间一个被锁定。我将第三个项目拖到第一个项目上。第一项应位于第三个元素的位置,而不是第二项位置。我不想用第一项替换第三项。 【参考方案1】:你需要做的是:
当用户移动单元格时,您将该单元格放入新的索引路径(如果要替换的那个没有锁定)。
然后对于已替换的行,您需要将其索引行移动 +1。这可能需要循环完成,您需要检查下一个单元格是否未锁定。如果它被锁定,那么您只需将该行再增加 1。例如:
CELL 1
CELL 2 - locked
CELL 3
我将CELL 3
移动到CELL 1
。然后您需要检查CELL 2
是否被锁定。如果是(如本例所示),则将CELL 1
移动到CELL 3
。
//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'.
【讨论】:
修改了我的帖子。 好吧,我不会为你写的。但可以添加一些。等等。以上是关于如何在锁定其中一些单元格时重新排序 UICollectionView 单元格的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableView (swift2) 中选择单元格时更新/重新加载 ViewController
UIView drawRect 仅在 UITableViewCell 中调用一次,导致重新使用单元格时数据过时
如何使用自定义按钮重新排序表格视图单元格,但不使用 ios 中的移动编辑图标