将垂直滚动手势传递给下方的UITableView

13

(为了更加清晰)

我有一个UITableView。在它上面是一个带有Pan手势的UIView。这个手势可以左右滑动以更改底层的表格。我使用手势的action方法来移动表格。这部分功能正常。

但是,UIView和它的Pan手势会干扰UITableView的上下滚动。如何将上下滚动发送到表格并保持左右滑动只在视图区域中进行?

 ---------------------------------------
 |                                     |
 |             ----------------------  |
 |             |                    |  |
 |             |                    |  |
 |             |                    |  |
 | UITableView |                    |  |
 |             |        UIView      |  |
 |             |          +         |  |
 |             |       PanGesture   |  |
 |             |                    |  |
 |             |                    |  |
 |             |                    |  |
 |             |                    |  |
 |             ----------------------  |
 |                                     |
 |                                     |
 ---------------------------------------

由Pan手势触发的方法如下

 -(void)move:(UIPanGestureRecognizer*)sender
 {
     CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
     float xTest = fabsf(translatedPoint.x);
     float yTest = fabsf(translatedPoint.y);
     if ( xTest>yTest)
     {
         // Move table view left-right.. this works
     } else
     {
         // Send up-down scrolling gesture to table view????? How to?
     }
 }
7个回答

11

我刚刚解决了一个类似的问题,只不过它是针对垂直滑动而不是水平滑动。我不确定你的使用情况是否完全相同,所以这可能不是你要找的东西,但它可能会引导你朝着正确的方向。

我子类化了UIPanGestureRecognizer,并实现了touchesMoved方法,并检查手势的水平或垂直变化是否更大。下面是一段代码片段。这个方法的来源归功于另一个stackoverflow帖子,但我目前找不到链接。(首次发布,请原谅格式不佳)

-(void)touchesMoved:(NSSet*) touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if(self.state == UIGestureRecognizerStateFailed) return;
CGPoint currentPoint = [[touches anyObject] locationInView:self.view];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view];
moveX += prevPoint.x - currentPoint.x;
moveY += prevPoint.y - currentPoint.y;
if(!drag) {
    if(abs(moveY) > abs(moveX))
        drag = YES;
    else
        self.state = UIGestureRecognizerStateFailed;
}
}

-(void)reset
{
[super reset];
drag = NO;
moveX = 0;
moveY = 0;
}

在我的父视图控制器中,我相信在这种情况下应该是UITableView,我还实现了以下内容。我认为在您的情况下,如果是水平滑动,您会想要返回no。

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if([gestureRecognizer isKindOfClass:[VerticalPanGestureRecognizer class]])
{
    return YES;
}
return NO;
}

如果有任何问题不清楚,请告诉我。

祝好运!


在我的情况下,父视图是一个UIViewController。我尝试了上面的代码,但仍然无法将滚动传递到表格。 - cannyboy

3

UIGestureRecognizer具有一个属性,可以防止识别出的手势将其事件转发到视图层次结构 - 这听起来就像是对你而言的正确选项。尝试在涉及到的手势识别器上设置它为NO

cancelsTouchesInView

一个布尔值,影响当手势被识别时是否将触摸传递给视图。

@property(nonatomic) BOOL cancelsTouchesInView

讨论

当此属性为YES(默认值)且接收器识别其手势时,该手势的待处理触摸不会传递到视图,并通过向视图发送touchesCancelled:withEvent:消息来取消之前传递的触摸。如果手势识别器未识别其手势或此属性的值为NO,则视图将接收多点触摸序列中的所有触摸。

iOS 3.2及更高版本可用。

来源:UIGestureRecognizer reference


2
这似乎没有任何影响。 - cannyboy

2

好的,答案是将pan添加到UITableView而不是UIView中。然后我检查手势的位置是否在(现在在xib中隐藏的)UIView的边界内,就像这样:

 - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
 {
     CGPoint translation = [gestureRecognizer locationInView:self.view];
     CGRect frame = self.slideTarget.frame;
     if (CGRectContainsPoint(frame, translation))
     {
         return YES;
     } else
     {
         return NO;
     }
 }

砰。


1

我理解您希望根据手势方向(垂直 -> 滚动表格,水平 -> 滚动UIView)处理UIView中的手势。我阅读了关于此事的资料-尚未尝试-:UISwipeGestureRecognizer具有方向属性-来自文档:

The permitted direction of the swipe for this gesture recognizer.

也许这可以帮到你?

编辑:哦,好吧,我没有意识到你正在查看一个UIPanRecognizer(太多的“滑动”了)...也许当平移的方向足够“垂直”时,你可以将手势传递给表格,如translationInView:所报告的那样..?


1
在您的Pan手势方法中编写以下内容:
- (void)pan:(UIPanGestureRecognizer *)gesture
{
    CGPoint translatedPoint = [gesture translationInView:self.tableView];

    if (ABS(translatedPoint.y) > 10.0f) {
        self.tableView.bounds = CGRectMake(0, -translatedPoint.y, 320, 460);
    }
    if (ABS(translatedPoint.x) > 10.0f) {
        // swipe left/right code...
    }
}

在这里,您可以通过更改表视图的边界属性来模拟滚动。但是,此代码不会使表视图反弹。可以通过在平移手势开始时保存反弹属性状态,然后在手势结束时分配此属性来实现此效果。


0

从您的需求中我可以理解到,您需要在与另一个视图交互时滚动表格。 因此,视图层将如下所示:

UINavigationController-->view (导航控制器将拥有UITableViewController) UITableViewController(它将拥有UITableView)

最后

UIView(UINavigationController.view子视图UIView)

因此,您希望如果您在UIView上进行平移(滚动),则您的TableView将正确滚动。

因此,您需要为所需的UIView(假设为CustomView)创建一个类。 然后在CustomView类中实现以下方法。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];

    // If the hitView is THIS view, return the view that you want to     receive the touch instead:
    if (hitView == self) {
        return _tableView;
    }
    else if ([hitView isKindOfClass:[UIButton class]]) {
        return hitView;
    }
    return _tableView;
}

如果您在CustomView中有一个按钮子视图,那么您也可以对其进行选择。
抱歉我的解释不够清晰,但我刚刚找到了这个解决方案,并想与您分享。
如果您需要更多的解释,请告诉我,我稍后会解释。

这段代码实际上会将控制权发送到TableView,您将不需要使用UIPanGesture来执行表格滚动。 - Mohd Haider

0

实现 UIGestureReconizerDelegate 方法,命名为 - gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:

默认情况下它返回 false,请实现并返回 true

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return true;
}

而且,不要忘记设置手势的delegate属性。
// Set the delegate of the panGesture. For example
self.panGestureReconizer.delegate = ... //

从苹果文档

(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

询问委托人是否应允许两个手势识别器同时识别手势。

返回值

YES表示允许 gestureRecognizer 和 otherGestureRecognizer 同时识别它们的手势。默认实现返回NO,表示不能同时识别两个手势。

讨论

当 gestureRecognizer 或 otherGestureRecognizer 的手势识别将阻止另一个手势识别器识别其手势时,将调用此方法。请注意,返回 YES 可确保同时识别;另一方面,返回 NO 不能保证防止同时识别,因为另一个手势识别器的代理可能返回 YES。


阅读更多


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接