通过手势交换单元格的位置

我有我有一个原型单元格和UIImageView UICollectionView我在UICollectionView中显示随机图像。

现在我想通过将它移动到附近的单元格来交换UIImageView的位置。我尝试了轻扫手势和长按手势。下面给出了我已经完成的代码:

 - (IBAction)LongPress:(UILongPressGestureRecognizer *)sender { if (sender.state != UIGestureRecognizerStateEnded) { return; } CGPoint p = [sender locationInView:self.collectionView]; NSIndexPath *indexPath = [self.coll_out indexPathForItemAtPoint:p]; if (indexPath == nil) { NSLog(@"couldn't find index path"); } else { // get the cell at indexPath (the one you long pressed) UICollectionViewCell* cell =[self.coll_out cellForItemAtIndexPath:indexPath]; // do stuff with the cell } } 

并且还尝试了委托方法:

 - (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath { NSMutableArray *item1=[arr_final objectAtIndex:indexPath.section]; NSMutableArray *item2=[arr_final objectAtIndex:newIndexPath.section]; NSLog(@"%@ %@",item1,item2); NSString *index = [item1 objectAtIndex:indexPath.item]; [item1 removeObjectAtIndex:indexPath.item]; [item2 insertObject:index atIndex:newIndexPath.item]; } 

function就像拖放一样。 我见过的例子

  • LXReorderableCollectionViewFlowLayout
  • HTKDragAndDropCollectionViewLayout

请给我正确的方法和代码刷到附近的单元格。 谢谢…

其实我一直在使用LXReorderableCollectionViewFlowLayout ,它非常适合你,它也有一个在他们的存储库的例子。 起初,我不build议你使用滑动手势,因为它与UICollectionView的内部手势处理高度冲突,但是如果你确实需要它,你必须实现增加手势的委托方法,并解决同时手势,因为它正在做LXReordableCollectionViewFlowLayout:

 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { if ([self.panGestureRecognizer isEqual:gestureRecognizer]) { return (self.selectedItemIndexPath != nil); } return YES; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { if ([self.longPressGestureRecognizer isEqual:gestureRecognizer]) { return [self.panGestureRecognizer isEqual:otherGestureRecognizer]; } if ([self.panGestureRecognizer isEqual:gestureRecognizer]) { return [self.longPressGestureRecognizer isEqual:otherGestureRecognizer]; } return NO; } 

反正我不build议你重新实现在LXReordableCollectionViewFlowLayout中完成的工作,只是将它用于你的需要。 如果使用Storyboard,则需要将UICollectionView放入UIViewController中,并将默认的UICollectionViewFlowLayout类更改为LXReorderableCollectionViewFlowLayout 在这里输入图像说明 另外,您的UICollectionView委托应符合下一个协议:LXReorderableCollectionViewDataSource(扩展UICollectionViewDataSource)和LXReorderableCollectionViewDelegateFlowLayout(扩展UICollectionViewDelegateFlowLayout)这些允许您使用您的类。 为了您的需要,只需提供下一个方法即可:

 - (void)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)fromIndexPath willMoveToIndexPath:(NSIndexPath *)toIndexPath { id from = [items objectAtIndex:fromIndexPath.item]; id to = [items objectAtIndex:toIndexPath.item]; [items replaceObjectAtIndex:fromIndexPath.item withObject:to]; [items replaceObjectAtIndex:toIndexPath.item withObject:from];; } - (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath { return YES; } - (BOOL)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)fromIndexPath canMoveToIndexPath:(NSIndexPath *)toIndexPath { return YES; } 

为了完全确定你需要的行为,你必须进入LXReorderableCollectionViewFlowLayout类,并更改invalidateLayoutIfNecessary方法,以便执行另一种更新而不是之前的方法:

 - (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]; } __weak typeof(self) weakSelf = self; [self.collectionView performBatchUpdates:^{ __strong typeof(self) strongSelf = weakSelf; if (strongSelf) { // NOTE: cells swipe [strongSelf.collectionView moveItemAtIndexPath:previousIndexPath toIndexPath:newIndexPath]; [strongSelf.collectionView moveItemAtIndexPath:newIndexPath toIndexPath:previousIndexPath]; // NOTE: it was here previously // [strongSelf.collectionView deleteItemsAtIndexPaths:@[ previousIndexPath ]]; // [strongSelf.collectionView insertItemsAtIndexPaths:@[ newIndexPath ]]; } } completion:^(BOOL finished) { __strong typeof(self) strongSelf = weakSelf; if ([strongSelf.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:didMoveToIndexPath:)]) { [strongSelf.dataSource collectionView:strongSelf.collectionView itemAtIndexPath:previousIndexPath didMoveToIndexPath:newIndexPath]; } }]; } 

对于靠近你的初始项目的细胞来说,效果很好,但是一旦你的卡片被移动了,它可能会误导使用者下一步移动它,反正只是试试看它是如何发生的。 请记住,您可以通过collectionView:itemAtIndexPath:canMoveToIndexPath:方法来控制项目的可用移动。

希望这对你有所帮助。