如何从UICollectionViewCell将pan手势传递给UICollectionVIew?

Cin*_*lia 8 objective-c foundation ios

UICollectionView实现了一个基于网格的自定义布局UICollectionViewCells.为了允许单元格响应拖动,我单独UIPanGestureRecognizer向每个单元格添加一个.

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

现在,我将水平左/右拖动与垂直向上/向下拖动分开,因此拖出单元格(垂直滑动)和滚动CollectionView(水平滑动)之间不应存在任何冲突.在这种情况下,如何将滑动传递到集合/滚动视图,以便它知道像正常一样滚动?不得不开始在细胞之间的边界或间隔是非常烦人的.

一旦我从一个单元格中移除了平移手势,无论我是开始在单元格上还是在单元格之间滑动,滚动都会正常工作.

编辑:下面发布的所需平移手势行为作为当前代码

// 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;
}
Run Code Online (Sandbox Code Playgroud)

该代码适用于每个单独的单元格.当附加到UICollectionView作为其手势识别器时它不起作用,并且它实际上停止所有滚动.

Ker*_*rrM 11

相反,附加的UIPanGestureRecognizer每个单元(这会降低性能)添加UIPanGestureRecognizerUICollectionView当移动手势恰好利用locationInView获得分数在UICollectionView锅里开始的地方,然后indexPathForItemAtPoint将返回你的索引路径,你应该动画细胞.

这样,你的整个集合视图中只有一个手势识别器(好!),同时在视图控制器中保持控制(如你所愿) - 双赢!

使用此解决方案,在您的视图控制器,你将实现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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

使用-shouldReceiveTouch:和-shouldRecognizeSimultaneouslyWithGestureRecognizer:返回YES,将UIGestureRecognizerDelegate添加为您的类协议列表,并将您的手势委托委托给自己的-viewDidLoad.

yourGesture.delegate = self;
Run Code Online (Sandbox Code Playgroud)