TableView 和 PKRevealController 手势冲突 - 如何真正解决它们?

Posted

技术标签:

【中文标题】TableView 和 PKRevealController 手势冲突 - 如何真正解决它们?【英文标题】:TableView and PKRevealController gesture conflicts - How to really solve them? 【发布时间】:2013-04-04 20:04:20 【问题描述】:

我正在尝试使用滑动侧边菜单实现视图,例如 ios 6.1 中的 PKRevealController。 A simple demo of this issue with source code on github is here,但是如果您已经了解了gestureRecognizer 委托实现,则可能不需要抓住它。

我看到的问题是,我的用户想要使用的两个手势会相互混淆。应用程序中心(主屏幕)中的 UITableView 应该能够使用向右滑动手势来删除,但我仍然希望在顶部导航区域发生滑动以暴露侧边菜单。我也打算显示除表格视图之外的其他内容,并且在运行时,每当用户在其中一个侧面菜单上选择一个按钮时,我计划将主视图换成不同的视图。这有点像我要使用的“隐藏侧托盘 UITabBarController”,但我希望仅当主“前视图”控制器不是 UITableView 或其子视图时才显示侧栏。

目前,使用PKRevealController自带的demo源码,并在主视图的UITableView中加入删除支持,没有滑动手势可以删除一行。 (您必须添加一种表格视图方法才能在 UITable 视图中启用删除支持,我确实添加了。)

这是here 提出的问题,但给出的答案不完整,如下所示,对我不起作用,我不知道为什么,因为似乎在我返回的任何时候都没有调用此委托方法是的,但无论如何它都会继续并开始一个手势。 更新与我在下面放置的 WIKI/FAQ 答案相比,上一个问题的答案也是错误的。

我只修改了 PKRevealController.m 类,添加了这个:

- (BOOL)                             gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 

    UIView *view1 = otherGestureRecognizer.view;
    UIView *view2;
    if (view1) 
         view2 = view1.superview;
    ;

    if ([gestureRecognizer.view isKindOfClass:[UITableView class]])
    
        return NO;
    
    // Co-operate by not stealing gestures from UITableView.
    if ([view1 isKindOfClass:[UITableView class]]) 
        return NO;
    else if ([view1 isKindOfClass:[UITableViewCell class]]) 
        return NO;
        // UITableViewCellContentView
    
    else if (view2 && [view2 isKindOfClass:[UITableViewCell class]]) 
        return NO;
        // UITableViewCellContentView
    
    else
    
        return YES;    // NEVER GETS HIT. BREAKPOINT HERE!
    

让我感到困惑的是,上面的返回 YES 代码在任何时候都没有被命中(我有一个断点),然而,手势控制器仍在窃取手势。

注意:我做了一个邪恶的黑客攻击,但我认为我可以干净地阻止这种情况。这是我的邪恶黑客:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

    if (gestureRecognizer == self.revealPanGestureRecognizer)
    
        CGPoint translation = [self.revealPanGestureRecognizer translationInView:self.frontViewContainer];
        BOOL begin = (fabs(translation.x) >= fabs(translation.y));

        // BEGIN EVIL HACK
        if (_topLimitY > 0) 
         CGPoint location = [gestureRecognizer locationInView:gestureRecognizer.view];
         if (location.y>_topLimitY) // _topLimitY = 55 for instance.
            begin = NO;
        
        // END EVIL HACK.

        return begin;
    
    else if (gestureRecognizer == self.revealResetTapGestureRecognizer)
    
        return ([self isLeftViewVisible] || [self isRightViewVisible]);
     

    return YES;

现在在我的恶意黑客演示中,我已将 topLimitY 属性(我添加到 PKRevealController 的属性中)设置为 55,这允许我在前视图的导航栏区域上滑动,但不能在表视图上滑动占用演示的其余部分。

请注意,我计划有多个主视图,并且如果视图是 UITableView 或其某些子视图,则只想在整个主区域上击败手势识别。这就是为什么我将我的 hack 称为 hack 之上的原因。因为我认为你可以告诉手势识别器离开而不打扰你,但它不起作用,它甚至没有调用 shouldRecognize 方法,它只是继续执行其列表中的下一个事情做。

【问题讨论】:

【参考方案1】:

我真的应该先阅读 WIKI,不是吗?

这是一个常见问题解答,它说得对here:

当实例化控制器时,在你的选项字典中传递这个选项:

  NSDictionary *options = @
      PKRevealControllerRecognizesPanningOnFrontViewKey : @NO
  ;

这将禁用整个前视图的基于平移的显示。现在,您可以使用revealPanGestureRecognizer 并将其添加到您希望在不干扰表格视图的情况下平移的任何视图中,以启用基于手势的显示。 我建议(如果使用带有可滑动单元格的基于表格的环境)你,将revealPanGestureRecognizer 添加到你的前视图控制器的导航栏(它很可能有):

  [self.navigationController.navigationBar addGestureRecognizer:self.revealController.revealPanGestureRecognizer];

瞧——平移不再干扰您的表格视图。

更多信息请访问: https://github.com/pkluz/PKRevealController/issues/76

谢谢你的维基。要是我先读完就好了。

以上内容完全回答了我的问题,并且已经出现在 wiki 上。我正在回答我自己的问题,因为 Google 似乎总是首先使用 ***,这可能会在未来帮助其他困惑的开发人员。

更新如果上面的事情在你尝试的时候失败了,那可能是做得太早了。这是上述修复的一个更强大的版本:

// Additional gesture recognition linkups. The underscore variables here
// are implementation-section ivars in my app-delegate,  that I have already 
// checked are valid and initialized, and this is the last thing in my app delegate
// didFinishLaunch... method, before the return YES:

UIGestureRecognizer *rec = _revealController.revealPanGestureRecognizer;
if (rec) 
    [_frontViewNavController.navigationBar addGestureRecognizer:rec];

【讨论】:

【参考方案2】:

使用这个:

self.revealController.frontViewController.revealController.recognizesPanningOnFrontView = YES;

【讨论】:

以上是关于TableView 和 PKRevealController 手势冲突 - 如何真正解决它们?的主要内容,如果未能解决你的问题,请参考以下文章

TableView - 标题和部分不正确

在 tableview 滚动和再次拖动 tableview 上动画 UIView 位置

tableView和scrollView滚动起冲突,tableview不能滚动

iOS tableView不让头部和尾部跟随

tableView.reloadData() 和 DispatchQueue 无法在不同的视图控制器中重新加载 tableview

展开和折叠 tableview 单元格