ios - 如何将平移手势从 UICollectionViewCell 传递给 UICollectionVIew?

标签 ios objective-c foundation

我有一个 UICollectionView 实现了自定义 UICollectionViewCells 的基于网格的布局。为了让单元格响应拖动,我分别向每个单元格添加了一个 UIPanGestureRecognizer

UICollectionView 当我向下触摸并从单元格之间的点开始向左/向右滑动时,UICollectionView 仍然滚动(水平),但只要将平移手势识别器添加到单元格,它似乎CollectionView 在单元格内开始轻扫时拒绝滚动。

现在,我将水平左/右拖动与垂直向上/向下拖动分开,因此拖出单元格(垂直滑动)和滚动 CollectionView(水平滑动)之间不应该有任何冲突.在这种情况下,我如何将滑动传递给集合/ ScrollView ,以便它知道像正常一样滚动?必须从单元格之间的边界或间距开始,这真的很烦人。

一旦我从单元格中移除平移手势,无论我是在单元格上还是在单元格之间开始滑动,滚动都会正常进行。

编辑:期望的平移手势行为作为当前代码发布在下面

// Handle pans by detecting swipes:
-(void) handlePan:(UIPanGestureRecognizer*)recognizer
{
    // Calculate touch location
    CGPoint touchXY = [recognizer locationInView:masterWindowView];

    // Handle touch
    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        gestureWasHandled = NO;
        pointCount = 1;
        startPoint = touchXY;
    }

    if (recognizer.state == UIGestureRecognizerStateChanged)
    {
        ++pointCount;

        // Calculate whether a swipe has occurred
        float dX = deltaX(touchXY, startPoint);
        float dY = deltaY(touchXY, startPoint);

        BOOL finished = YES;
        if ((dX > kSwipeDragMin) && (ABS(dY) < kDragLimitMax)) {
            touchType = TouchSwipeLeft;
            NSLog(@"LEFT swipe detected");
            [recognizer requireGestureRecognizerToFail:recognizer];
            //[masterScrollView handlePan]
        }
        else if ((dX < -kSwipeDragMin) && (ABS(dY) < kDragLimitMax)) {
            touchType = TouchSwipeRight;
            NSLog(@"RIGHT swipe detected");
            [recognizer requireGestureRecognizerToFail:recognizer];
        }
        else if ((dY > kSwipeDragMin) && (ABS(dX) < kDragLimitMax)) {
            touchType = TouchSwipeUp;
            NSLog(@"UP swipe detected");
        }
        else if ((dY < -kSwipeDragMin) && (ABS(dX) < kDragLimitMax)) {
            touchType = TouchSwipeDown;
            NSLog(@"DOWN swipe detected");
        }
        else
            finished = NO;

        // If unhandled and downward, produce a new draggable view
        if (!gestureWasHandled && finished && (touchType == TouchSwipeDown))
        {

            [self.delegate cellBeingDragged:self];
            dragView.center = touchXY;
            dragView.hidden = NO;
            dragView.backgroundColor = [UIColor clearColor];


            masterScrollView.scrollEnabled = NO; // prevent user from scrolling during
            gestureWasHandled = YES;
        }
        else if (gestureWasHandled)
        {
            // allow continued dragging after detection
            dragView.center = touchXY;
        }
    }

    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        // ensure that scroll view returns to scrollable
        if (gestureWasHandled) {
            [self.delegate cell:self dragEndedAt:touchXY];
        }
    }
}

// Allow simultaneous recognition
-(BOOL) gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
    return YES;
}

此代码在提供给每个单独的单元格时有效。当附加到 UICollectionView 作为其手势识别器时,它不起作用,实际上它会停止所有滚动。

最佳答案

与其将 UIPanGestureRecognizer 附加到每个单元格(这会降低性能),不如将 UIPanGestureRecognizer 添加到 UICollectionView 并在平移手势发生时使用 locationInView在平移开始的 UICollectionView 中获取点,然后是 indexPathForItemAtPoint这将返回您应该设置动画的单元格的索引路径。

这样一来,您的整个 Collection View 将只有一个手势识别器(很好!),同时还可以在 View Controller 中保持控制(如您所愿)——双赢!

使用此解决方案,您将在 View Controller 中实现 gestureRecognizer:shouldReceiveTouch: ,捕获给定的 gestureRecognizer,确保它是你的 UIPanGestureRecognizer 并使用它的 translationInView: 方法来确定翻译是在 X 轴还是 Y 轴上。使用该信息来决定是否要返回 YES 或 NO。例如:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
  if([gestureRecognizer isEqual:myTapGesture]) {
    CGPoint point = [gestureRecognizer translationInView:self.collectionView];
    if(point.x != 0) { //adjust this condition if you want some leniency on the X axis
      //The translation was on the X axis, i.e. right/left, 
      //so this gesture recognizer shouldn't do anything about it
      return NO;
    }
  }
  return YES;
}

关于ios - 如何将平移手势从 UICollectionViewCell 传递给 UICollectionVIew?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23776092/

相关文章:

ios - Swift:在没有 dequeueReusableCellWithIdentifier 的情况下创建静态自定义单元格

ios - iOS App Store 对 Apple 版本有什么要求?

iphone - 使用 Quartz 层是否会降低 UITableView 滚动性能?

objective-c - 从 NSMutableArray 复制对象的正确方法是什么

ios - 如何使用 NSURLAuthenticationMethodservertrust 触发 URLAuthenticationChallenge

ios - CoreData 和中间体

iphone - objective-c 中UITableView中的UILabel

ios - 更好的是,委托(delegate)或单例在 View Controller 之间传递数据 - Objective-C

multithreading - NSIndexPath 线程安全吗?

cocoa - 新的 iOS9/OSX10.11 NSNumberFormatter Style 枚举值是什么意思?