通过手势交换细胞的位置

时间:2015-12-28 10:15:04

标签: ios objective-c drag-and-drop uiimageview uicollectionview

我有UICollectionView,其中有一个原型单元格和UIImageView。我正在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];
}

功能就像拖放一样。我见过

的例子

请给我正确的方法和代码,以便滑到附近的单元格。 感谢...

1 个答案:

答案 0 :(得分:3)

实际上我一直在使用LXReorderableCollectionViewFlowLayout,它非常适合你,它的存储库中也有一个例子。起初我不建议您使用滑动手势,因为它与UICollectionView的内部手势处理高度冲突,但如果您确定需要它,则必须实现委派方法以添加手势并解决同时手势,因为它正在执行LXReordableCollectionViewFlowLayout:< / p>

- (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;
}

无论如何我不建议你重新实现在LXReordableCollectionViewFlowLayout中完成的工作,只是根据你的需要使用它。如果您正在使用Storyboard,则需要将UICollectionView放入UIViewController,并将默认的UICollectionViewFlowLayout类更改为LXReorderableCollectionViewFlowLayout,就像enter image description here一样。 您的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:方法控制项目的可用移动。

希望这对你有所帮助。