如何将 UICollectionViewCell 从一个 UICollectionView 拖到另一个 UICollectionView?

Posted

技术标签:

【中文标题】如何将 UICollectionViewCell 从一个 UICollectionView 拖到另一个 UICollectionView?【英文标题】:How can I drag a UICollectionViewCell from one UICollectionView to another UICollectionView? 【发布时间】:2013-06-21 14:38:46 【问题描述】:

我正在制作一个 iPad 应用程序。在此应用程序的一个页面上,左侧有一个 UICollectionView,右侧有另一个 UICollectionView。每个 UICollectionView 都是一列宽。

我想要的功能如下: 左侧的每个 UICollectionViewCell 都应该能够拖到右侧的 UICollectionView 上。如果这是不可能的,那么至少应该能够将一个 UICollectionViewCell 拖出左侧 UICollectionView,然后我会处理让它出现在右侧 UICollectionView 中。

这个功能可行吗?如果是这样,我将如何实施它?

【问题讨论】:

【参考方案1】:

您可能希望将长按手势识别器附加到两个 collectionView 的公共超级视图。拖动操作由长按触发,整个事务在该识别器中处理。因为平移手势用于滚动集合视图,所以在尝试使用平移识别器时会遇到问题。

关键是手势识别器需要附加COMMON superview,所有点和矩形都转换到superview的坐标系。

这不是确切的代码(这会从 CV 转移到另一个视图),但过程类似(注意:我试图删除一些与您的应用程序无关的代码,所以我可能搞砸了在这个过程中有些东西——但这个概念是成立的):

- (void) processLongPress:(UILongPressGestureRecognizer *)sender

if (sender.state == UIGestureRecognizerStateChanged)

    if (!dragView)
        return;
    CGPoint location = [sender locationInView:self.view];
    CGPoint translation;
    translation.x = location.x - dragViewStartLocation.x;
    translation.y = location.y - dragViewStartLocation.y;
    CGAffineTransform theTransform = dragView.transform;
    theTransform.tx = translation.x;
    theTransform.ty = translation.y;
    dragView.transform = theTransform;
    [self.view bringSubviewToFront:dragView];
    return;
   

if (sender.state == UIGestureRecognizerStateBegan)

    //  if point gives a valid collectionView indexPath we are doing a long press on a picture item to begin a drag
    //  & drop operation.
    CGPoint point = [sender locationInView:collectionView];
    dragViewIndexPath = [collectionView indexPathForItemAtPoint:point];
    if (dragViewIndexPath)  // i.e., selected item in collection view.
    
        UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:dragViewIndexPath];
        dragView = [cell.contentView viewWithTag:cell.tag];
        [dragView removeFromSuperview];
        [self.view addSubview:dragView];
        dragView.center = [collectionView convertPoint:point toView:self.view];
        dragViewStartLocation = dragView.center;
        [self.view bringSubviewToFront:dragView];
    
    return;


if (sender.state == UIGestureRecognizerStateEnded)

    if (dragView)
    
        dragView.center = CGPointMake(dragView.center.x + dragView.transform.tx, dragView.center.y + dragView.transform.ty);
        CGAffineTransform theTransform = dragView.transform;
        theTransform.tx = 0.0f;
        theTransform.ty = 0.0f;
        UIView *dropTarget = [self mapDisplayModeToReceiverView];   // get drop target

        CGRect convertedTargetFrame = [self.view convertRect:dropTarget.frame fromView:dropTarget.superview];
        if (CGRectContainsPoint(convertedTargetFrame, dragView.center)) // if so, then drop it.
        
            ImageWithAttachedLabel *i = (ImageWithAttachedLabel *) dragView;
            [speakStrings addObject:[i.labelText stringByAppendingString:@". "]];
            UserData *uData = (UserData *)i.userDataObject;
            UIImage *image = [[UIImage alloc] initWithData:uData.image];
            CGRect newFrame = CGRectMake(0.0f, 0.0f, 140.0f, 140.0f);
            ImageWithAttachedLabel *newImage = [[ImageWithAttachedLabel alloc] initWithFrame:newFrame withImage:image withLabel:uData.itemName];
            newImage.tag = RECEIVERVIEW_MAGIC_NUMBER;
            [self.view addSubview:newImage];
            newImage.center = [receiverView convertPoint:dropTarget.center toView:self.view];
            [UIView animateWithDuration:0.35f animations:^ newImage.transform = CGAffineTransformMakeScale(1.15f, 1.15f); newImage.transform = CGAffineTransformIdentity; 
                             completion:^(BOOL finished)   if (finished)
                                                            
                                                                [newImage removeFromSuperview];
                                                                newImage.frame = newFrame;
                                                                [dropTarget addSubview:newImage];
                                                                [dragView removeFromSuperview];
                                                                dragView=nil; 
                                                            ];

        
        else
        
            [dragView removeFromSuperview];
            dragView = nil;
        

        [self reloadData];
        return;
    

【讨论】:

你好@regularExpression,你的代码中的dragView是什么? 嗨,dragView 只是一个指向正在拖动的 UIView 的指针。它设置为手势识别器“StateBegan”代码中被拖动的视图:dragView = [cell.contentView viewWithTag:cell.tag] 在这种情况下,视图是集合视图中单元格的内容,但它确实可以是任何观点。【参考方案2】:

实际上无法将一个单元格从一个集合“传递”到另一个集合,但您可以执行以下操作:

1) 一旦您检测到用户拖动了另一个集合中的单元格,请从第一个集合中删除该单元格(我们称之为集合 1)。您也许可以使用漂亮的淡入淡出动画来使单元格消失。

2) 向第二个表格添加一个带有漂亮动画的单元格(请参阅 UICollectionView 和 UICollectionViewLayout 方法和委托方法)。

【讨论】:

谢谢,这很有道理。我怎样才能实现具有可拖动单元格?我需要使用LXReorderableCollectionViewFlowLayout 之类的东西吗?或者有没有更简单的资源可以指点我?谢谢。 您可以使用此 LXReorderableCollectionViewFlowLayout,它还允许您使用手势对单元格进行排序,或者在手势开始时将 UIPanGestureRecognizer 添加到您的集合中(UICollectionView 有一种方法),然后当用户拖动单元格时相应地移动它。当手势结束或取消时,您可以检查单元格的位置并采取相应措施。 再次感谢,第二个选项听起来正是我正在寻找的,也很容易实现。 不客气。由于我注意到您对社区很陌生,因此我只想让您注意到您可以“接受”答案,并且随着您的声誉增长,您还将获得一些特权。您将首先得到的一个是“赞成”好的答案或“反对”不好的答案。如果您喜欢,请随时接受我的回答;)

以上是关于如何将 UICollectionViewCell 从一个 UICollectionView 拖到另一个 UICollectionView?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UICollectionViewCell 高度设置为视图(屏幕)高度的 90%?

如何将导航栏移到 UICollectionViewCell 之外?

如何将 UIView 约束为 UICollectionViewCell

如何将 UICollectionViewCell 放在前面?

如何将 UICollectionViewCell 嵌套在另一个中?

如何将 UITapGestureRecognizer 添加到 UICollectionViewCell 中的图像