简体   繁体   English

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

[英]How to pass pan gesture to UICollectionVIew from UICollectionViewCell?

I have a UICollectionView implementing a grid-based layout of custom UICollectionViewCells . 我有一个UICollectionView实现自定义UICollectionViewCells的基于网格的布局。 To allow cells to respond to dragging, I individually add a UIPanGestureRecognizer to each cell. 为了允许单元格响应拖动,我单独向每个单元格添加UIPanGestureRecognizer

The UICollectionView still scrolls (horizontally) when I touch down and swipe left/right starting at points between cells, but as long as the pan gesture recognizer is added to a cell, it seems like the CollectionView refuses to scroll when I start my swipe tapping within a cell. 当我向下触摸并从单元格之间的点开始向左/向右滑动时, UICollectionView仍然(水平地)滚动,但只要将平移手势识别器添加到单元格中,看起来当我开始轻扫时, CollectionView拒绝滚动在细胞内。

Right now, I separate horizontal left/right drags from vertical up/down drags, so there should not be any conflict between dragging cells out (vertical swipes) and scrolling the CollectionView (Horizontal swipes). 现在,我将水平左/右拖动与垂直向上/向下拖动分开,因此拖出单元格(垂直滑动)和滚动CollectionView (水平滑动)之间不应存在任何冲突。 In this case, how can I pass the swipe to the collection/scroll view so it knows to scroll like normal? 在这种情况下,如何将滑动传递到集合/滚动视图,以便它知道像正常一样滚动? It's really annoying to have to start on the boundary or spacing between cells. 不得不开始在细胞之间的边界或间隔是非常烦人的。

Once I remove the pan gesture from a cell, scrolling works as normal no matter if I start swiping on a cell or between cells. 一旦我从一个单元格中移除了平移手势,无论我是开始在单元格上还是在单元格之间滑动,滚动都会正常工作。

EDIT:Desired pan gesture behavior posted below as current code 编辑:下面发布的所需平移手势行为作为当前代码

// 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;
}

This code works when given to each individual cell. 该代码适用于每个单独的单元格。 It does NOT work when attached to the UICollectionView as its gesture recognizer, and it in fact stops all scrolling. 当附加到UICollectionView作为其手势识别器时它不起作用,并且它实际上停止所有滚动。

Instead of attaching a UIPanGestureRecognizer to each cell (which will decrease performance) add a UIPanGestureRecognizer to the UICollectionView and when the pan gesture happens use locationInView to get the point in the UICollectionView where the pan started, and then indexPathForItemAtPoint which will return you the index path for the cell you should animate. 相反,附加的UIPanGestureRecognizer每个单元(这会降低性能)添加UIPanGestureRecognizerUICollectionView当移动手势恰好使用locationInView获得分数在UICollectionView泛开始的地方,然后indexPathForItemAtPoint将返回你的索引路径对于你应该动画的单元格。

This way, you will have only one gesture recognizer (good!) for your whole collection view while also maintaining the control in your view controller (as you wanted) - double win! 这样,你的整个集合视图中只有一个手势识别器(好!),同时在视图控制器中保持控制(如你所愿) - 双赢!

Using this solution, in your view controller you would implement gestureRecognizer:shouldReceiveTouch: , grab the given gestureRecognizer, make sure it's your UIPanGestureRecognizer and use its translationInView: method to find out if the translation is on the X or Y axis. 使用此解决方案,在视图控制器中,您将实现gestureRecognizer:shouldReceiveTouch:,获取给定的gestureRecognizer,确保它是您的UIPanGestureRecognizer并使用其translationInView:方法来确定转换是在X轴还是Y轴上。 Use that information to decide whether you want to return YES or NO. 使用该信息来决定是否要返回YES或NO。 For example: 例如:

- (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;
}

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

yourGesture.delegate = self;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM