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

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

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

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

【问题讨论】:

    标签: ios ipad ios6 uicollectionview uicollectionviewcell


    【解决方案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 有一种方法),然后当用户拖动单元格时相应地移动它。当手势结束或取消时,您可以检查单元格的位置并采取相应措施。
    • 再次感谢,第二个选项听起来正是我正在寻找的,也很容易实现。
    • 不客气。由于我注意到您对社区很陌生,因此我只想让您注意到您可以“接受”答案,并且随着您的声誉增长,您还将获得一些特权。您将首先得到的一个是“赞成”好的答案或“反对”不好的答案。如果您喜欢,请随时接受我的回答;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多