平移后,单元格停止响应选择

时间:2014-04-25 19:55:52

标签: ios objective-c selection uicollectionviewcell pan

问题:

完成平移手势后,初始点击下的单元格不再响应选择。 didSelectItemAtIndexPath将在点击其他单元格时触发,但不会触发平移手势下的单元格。

如何让该单元格再次响应触摸输入?或者,我如何检查该单元是否卡住了响应事件?

背景:

  • 我有一堆带有一堆单元格的UICollectionView。点击此集合视图中的单元格会触发didSelectItemAtIndexPath。
  • 集合视图具有平移手势识别器。平移会创建视图图像并将其平移到屏幕上。在平移手势的持续时间内,集合视图将保留在其他视图的下方。

理论:

由于平底锅,选择可能永远不会完成。也许在UI中有一个触摸事件。如果我能清除它,也许细胞会再次响应。我尝试设置[panHandler setCancelsTouchesInView:YES],但它没有改变任何内容。

更新1:

在评论中,有几个人建议图像可能会悬空并阻挡触摸。在传递给animateWithDuration的完成块中,我有以下几行:

[self.regionScreenshot removeFromSuperview];
self.regionScreenshot = nil;

我确认这些行已经执行。

让我相信不是问题的另一个因素是,在所有细胞中,只有已经习惯拖曳的细胞受到影响。周围的细胞仍在响应。

更新2:代码& GIF

- (IBAction)handlePanFrom:(UIPanGestureRecognizer*)recognizer
{
    CGPoint translation = [recognizer translationInView:recognizer.view];
    float transparencyLevel = 0.85;

    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        SFCYRegion* centerRegion = self.region;

        //North
        if (centerRegion.regionToNorth != nil)
        {
            self.region = centerRegion.regionToNorth;
            [self reloadRegion];
            self.regionToNorthScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToNorthScreenshot = [[UIView alloc] init];
            self.regionToNorthScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToNorthScreenshot];
        self.regionToNorthScreenshot.alpha = transparencyLevel;
        self.regionToNorthScreenshot.frame = northFrame;

        //East
        if (centerRegion.regionToEast != nil)
        {
            self.region = centerRegion.regionToEast;
            [self reloadRegion];
            self.regionToEastScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToEastScreenshot = [[UIView alloc] init];
            self.regionToEastScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToEastScreenshot];
        self.regionToEastScreenshot.alpha = transparencyLevel;
        self.regionToEastScreenshot.frame = eastFrame;

        //South
        if (centerRegion.regionToSouth != nil)
        {
            self.region = centerRegion.regionToSouth;
            [self reloadRegion];
            self.regionToSouthScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToSouthScreenshot = [[UIView alloc] init];
            self.regionToSouthScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToSouthScreenshot];
        self.regionToSouthScreenshot.alpha = transparencyLevel;
        self.regionToSouthScreenshot.frame = southFrame;

        //West
        if (centerRegion.regionToWest != nil)
        {
            self.region = centerRegion.regionToWest;
            [self reloadRegion];
            self.regionToWestScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToWestScreenshot = [[UIView alloc] init];
            self.regionToWestScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToWestScreenshot];
        self.regionToWestScreenshot.alpha = transparencyLevel;
        self.regionToWestScreenshot.frame = westFrame;

        //Northeast
        if (centerRegion.regionToNorth != nil && centerRegion.regionToNorth.regionToEast != nil)
        {
            self.region = centerRegion.regionToNorth.regionToEast;
            [self reloadRegion];
            self.regionToNortheastScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToNortheastScreenshot = [[UIView alloc] init];
            self.regionToNortheastScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToNortheastScreenshot];
        self.regionToNortheastScreenshot.alpha = transparencyLevel;
        self.regionToNortheastScreenshot.frame = northeastFrame;

        //Southeast
        if (centerRegion.regionToSouth != nil && centerRegion.regionToSouth.regionToEast != nil)
        {
            self.region = centerRegion.regionToSouth.regionToEast;
            [self reloadRegion];
            self.regionToSoutheastScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToSoutheastScreenshot = [[UIView alloc] init];
            self.regionToSoutheastScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToSoutheastScreenshot];
        self.regionToSoutheastScreenshot.alpha = transparencyLevel;
        self.regionToSoutheastScreenshot.frame = southeastFrame;

        //Southwest
        if (centerRegion.regionToSouth != nil && centerRegion.regionToSouth.regionToWest != nil)
        {
            self.region = centerRegion.regionToSouth.regionToWest;
            [self reloadRegion];
            self.regionToSouthwestScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToSouthwestScreenshot = [[UIView alloc] init];
            self.regionToSouthwestScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToSouthwestScreenshot];
        self.regionToSouthwestScreenshot.alpha = transparencyLevel;
        self.regionToSouthwestScreenshot.frame = southwestFrame;

        //Northwest
        if (centerRegion.regionToNorth != nil && centerRegion.regionToNorth.regionToWest != nil)
        {
            self.region = centerRegion.regionToNorth.regionToWest;
            [self reloadRegion];
            self.regionToNorthwestScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        }
        else
        {
            self.regionToNorthwestScreenshot = [[UIView alloc] init];
            self.regionToNorthwestScreenshot.backgroundColor = [UIColor darkGrayColor];
        }
        [self.view.superview addSubview:self.regionToNorthwestScreenshot];
        self.regionToNorthwestScreenshot.alpha = transparencyLevel;
        self.regionToNorthwestScreenshot.frame = northwestFrame;



        //Self
        self.region = centerRegion;
        [self reloadRegion];
        self.regionScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
        self.regionScreenshot.frame = mainFrame;
        self.regionScreenshot.center = mainFrameCenter;
        [self.view.superview addSubview:self.regionScreenshot];

        self.collectionView.alpha = 0;
    }
    else if (recognizer.state == UIGestureRecognizerStateChanged)
    {
        //Track the movement:
        self.regionScreenshot.center = [self movePoint:mainFrameCenter
                                                   byX:translation.x andY:translation.y];
        self.regionToNorthScreenshot.center = [self movePoint:northFrameCenter
                                                          byX:translation.x andY:translation.y];
        self.regionToEastScreenshot.center = [self movePoint:eastFrameCenter
                                                         byX:translation.x andY:translation.y];
        self.regionToSouthScreenshot.center = [self movePoint:southFrameCenter
                                                          byX:translation.x andY:translation.y];
        self.regionToWestScreenshot.center = [self movePoint:westFrameCenter byX:translation.x andY:translation.y];
        self.regionToNortheastScreenshot.center = [self movePoint:northeastFrameCenter
                                                              byX:translation.x andY:translation.y];
        self.regionToSoutheastScreenshot.center = [self movePoint:southeastFrameCenter
                                                              byX:translation.x andY:translation.y];
        self.regionToSouthwestScreenshot.center = [self movePoint:southwestFrameCenter
                                                              byX:translation.x andY:translation.y];
        self.regionToNorthwestScreenshot.center = [self movePoint:northwestFrameCenter
                                                              byX:translation.x andY:translation.y];

        //[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    }
    else if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        SFCYRegion* newRegion;
        UIView* viewToMoveToCenter;
        CGSize slideVector;
        NSInteger movedByX = 0;
        NSInteger movedByY = 0;

        float thresholdPercentage = 0.4;
        BOOL isOverThresholdToNorth = translation.y > (mainFrame.size.height * thresholdPercentage);
        BOOL isOverThresholdToSouth = -translation.y > (mainFrame.size.height * thresholdPercentage);
        BOOL isOverThresholdToEast = -translation.x > (mainFrame.size.width * thresholdPercentage);
        BOOL isOverThresholdToWest = translation.x > (mainFrame.size.width * thresholdPercentage);

        if (isOverThresholdToNorth && self.region.regionToNorth != nil)
        {
            movedByY = -1;

            if (isOverThresholdToEast && self.region.regionToNorth.regionToEast != nil)
            {
                //Northeast
                newRegion = self.region.regionToNorth.regionToEast;
                viewToMoveToCenter = self.regionToNortheastScreenshot;
                movedByX = 1;
            }
            else if (isOverThresholdToWest && self.region.regionToNorth.regionToWest != nil)
            {
                //Northwest
                newRegion = self.region.regionToNorth.regionToWest;
                viewToMoveToCenter = self.regionToNorthwestScreenshot;
                movedByX = -1;
            }
            else
            {
                //North
                newRegion = self.region.regionToNorth;
                viewToMoveToCenter = self.regionToNorthScreenshot;
            }
        }
        else if (isOverThresholdToSouth && self.region.regionToSouth != nil)
        {
            movedByY = 1;

            if (isOverThresholdToEast && self.region.regionToSouth.regionToEast != nil)
            {
                //Southeast
                newRegion = self.region.regionToSouth.regionToEast;
                viewToMoveToCenter = self.regionToSoutheastScreenshot;
                movedByX = 1;
            }
            else if (isOverThresholdToWest && self.region.regionToSouth.regionToWest != nil)
            {
                //Southwest
                newRegion = self.region.regionToSouth.regionToWest;
                viewToMoveToCenter = self.regionToSouthwestScreenshot;
                movedByX = -1;
            }
            else
            {
                //South
                newRegion = self.region.regionToSouth;
                viewToMoveToCenter = self.regionToSouthScreenshot;
            }
        }
        else if (isOverThresholdToEast && self.region.regionToEast != nil)
        {
            //East
            newRegion = self.region.regionToEast;
            viewToMoveToCenter = self.regionToEastScreenshot;
            movedByX = 1;
        }
        else if (isOverThresholdToWest && self.region.regionToWest != nil)
        {
            //West
            newRegion = self.region.regionToWest;
            viewToMoveToCenter = self.regionToWestScreenshot;
            movedByX = -1;
        }
        else
        {
            //None, so return to start:
            newRegion = self.region;
            viewToMoveToCenter = self.regionScreenshot;
        }

        slideVector = CGSizeMake(mainFrameCenter.x - viewToMoveToCenter.center.x,
                                 mainFrameCenter.y - viewToMoveToCenter.center.y);

        [UIView animateWithDuration:0.2
                         animations:^
         {
             viewToMoveToCenter.alpha = 1;
             if (![self.regionScreenshot isEqual:viewToMoveToCenter])
             {
                 self.regionScreenshot.alpha = transparencyLevel;
             }
             self.regionScreenshot.center = [self movePoint:self.regionScreenshot.center
                                                        byX:slideVector.width andY:slideVector.height];
             self.regionToNorthScreenshot.center =  [self movePoint:self.regionToNorthScreenshot.center
                                                                byX:slideVector.width andY:slideVector.height];
             self.regionToEastScreenshot.center =  [self movePoint:self.regionToEastScreenshot.center
                                                               byX:slideVector.width andY:slideVector.height];
             self.regionToSouthScreenshot.center =  [self movePoint:self.regionToSouthScreenshot.center
                                                                byX:slideVector.width andY:slideVector.height];
             self.regionToWestScreenshot.center =  [self movePoint:self.regionToWestScreenshot.center
                                                               byX:slideVector.width andY:slideVector.height];
             self.regionToNortheastScreenshot.center = [self movePoint:self.regionToNortheastScreenshot.center
                                                                   byX:slideVector.width andY:slideVector.height];
             self.regionToSoutheastScreenshot.center = [self movePoint:self.regionToSoutheastScreenshot.center
                                                                   byX:slideVector.width andY:slideVector.height];
             self.regionToSouthwestScreenshot.center = [self movePoint:self.regionToSouthwestScreenshot.center
                                                                   byX:slideVector.width andY:slideVector.height];
             self.regionToNorthwestScreenshot.center = [self movePoint:self.regionToNorthwestScreenshot.center
                                                                   byX:slideVector.width andY:slideVector.height];
         }
                         completion:^(BOOL finished)
         {
             if (finished)
             {
                 //Remove the old views:
                 self.collectionView.alpha = 1;
                 [self.regionScreenshot removeFromSuperview];
                 [self.regionToNorthScreenshot removeFromSuperview];
                 [self.regionToEastScreenshot removeFromSuperview];
                 [self.regionToSouthScreenshot removeFromSuperview];
                 [self.regionToWestScreenshot removeFromSuperview];
                 [self.regionToNortheastScreenshot removeFromSuperview];
                 [self.regionToSoutheastScreenshot removeFromSuperview];
                 [self.regionToSouthwestScreenshot removeFromSuperview];
                 [self.regionToNorthwestScreenshot removeFromSuperview];
                 self.regionScreenshot = nil;
                 self.regionToNorthScreenshot = nil;
                 self.regionToEastScreenshot = nil;
                 self.regionToSouthScreenshot = nil;
                 self.regionToWestScreenshot = nil;
                 self.regionToNortheastScreenshot = nil;
                 self.regionToSoutheastScreenshot = nil;
                 self.regionToSouthwestScreenshot = nil;
                 self.regionToNorthwestScreenshot = nil;
             }
         }];

        if (![self.regionScreenshot isEqual:viewToMoveToCenter])
        {
            self.region = newRegion;
            [self reloadRegion];
            [self movedRegionByX:movedByX andY:movedByY];
        }

        [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    }
}

这是一张展示此问题的图片。我在“郊区”单元格上执行选择,然后平移,然后我不再能够对该单元格执行选择,但仍然可以选择其他单元格: Animation of bug

更新3:所有手势

当我滑动手势和捏手势时也会发生这种情况。如果我添加双指滑动手势,原点下的两个单元都会受到影响。

2 个答案:

答案 0 :(得分:1)

确保regionScreenshot以及您添加到视图层次结构的任何其他视图都将userInteractionEnabled设置为NO

同时将您的单元格及其内容的clipsToBounds设置为YES。有时视图看起来不错,但实际上它们“比它们看起来要小得多”。

答案 1 :(得分:1)

当我平移时,我在生成用于相邻区域的屏幕截图的过程中调用了[self.collectionView reloadData]。在手势处于活动状态时重新加载细胞似乎会干扰个体细胞处理手势的能力。

作为一种解决方法,我改为向控制器添加第二个隐藏的UICollectionView,并将数据加载到该视图中并获取它的屏幕截图而不是主视图。在完成手势并选择新区域之前,主集合视图永远不必重新加载数据。

UIView* aScreenshot = [self.secondaryCollectionView snapshotViewAfterScreenUpdates:YES];