【问题标题】:Handling UIPanGestureRecognizer gestures for multiple Views (one covers the other)处理多个视图的 UIPanGestureRecognizer 手势(一个覆盖另一个)
【发布时间】:2015-07-11 21:36:56
【问题描述】:

很抱歉问了这么长的问题,但我觉得我应该传达我的尝试。

我在导航控制器中有一个视图viewA。然后,我将一个子视图viewB(包含UITableView)添加到viewA,并偏移其原始高度,使其仅覆盖屏幕的一半(另一半溢出屏幕底部)。然后我希望能够向上拖动这个viewB,但是当它到达导航栏的底部时它会停止,并且当它到达原点偏移点时同样会停止。我已经成功实现了这一点。

但是,我希望 UITableView 交互仅在 viewB 位于其上方位置时启用,因此不会响应任何其他位置的手势。本质上,向上拖动viewB 使其完全覆盖viewA 应该能够与UITableView 交互。

这里的棘手部分是我希望它执行以下操作:

  1. 如果viewB 位于其上方位置以覆盖屏幕,则UITableView 内容偏移量为0(即我们位于表格顶部)并且用户做出向下平移手势,手势不应与UITableView 交互,但应向下移动viewB
  2. 上述条件下的任何其他平移手势都应该是与UITableView 的交互。
  3. 如果viewB 位于其上方以覆盖屏幕,则UITableView 内容偏移量为 NOT 为 0(即我们是 NOT表顶部)并且用户做出向下平移手势,该手势应与UITableView交互。

我已经非常接近实现这一目标,但我无法做到完全正确。

目前的尝试

我正在使用UIPanGestureRecognizer 来处理视图的拖动。我已尝试将其添加到:

  • viewB 最初禁用了 UITableView 用户交互。这让我可以在不干扰UITableView 的情况下上下拖动viewB。一旦viewB 位于其上方位置,我将启用UITableView 用户交互,然后正确地允许我与UITableView 交互而无需移动viewB

    但是,通过启用 UITableView 用户交互,这意味着触摸永远不会到达 UIPanGestureRecognizer,这意味着我永远无法检测到上面第 (1.) 点中描述的场景,因此无法重新禁用 UITableView用户交互使viewB 再次可移动。

    也许可以通过覆盖UITableView 使用的手势识别方法来做到这一点?如果这是可能的,谁能指出我正确的方向?

  • UITableView 前面添加了一个新视图。我想也许我可以在必要时将触摸手势转发到它后面的UITableView,但我仍然没有找到这样做的方法。

    我所能做的就是禁用允许我与UITableView 交互的手势识别器,但是我遇到了与上述相同的问题。我无法检测到何时重新启用它。

  • viewB 中的UITableView。这似乎是迄今为止最有希望的方式。通过设置以下方法的返回值,我可以启用和禁用viewBUITableView 的识别。

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        if pulloverVC.view.frame.origin.y == bottomNavbarY &&
            pulloverVC.tableView?.contentOffset.y == 0 { // need to add gesture direction check to this condition
            viewBisAtTop = true
            return false // disable pullover control
        }
        return true // enable pullover control
    }
    
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if (gestureRecognizer as! UIPanGestureRecognizer).velocityInView(view).y < 0 && viewBisAtTop { // gesture direction check not wanted here
            return true // enable tableview control
        }
        viewBisAtTop = false
        return false // disable tableview control
    }
    

    做出手势时首先调用 top 方法(我已经检查了 print 语句),然后调用 bottom 方法。通过为这两种方法制作不同的真/假组合,我可以在viewBUITableView 之间交替交互。

    为了检测用户是否向下滑动,我在识别器上调用velocityInView()(如底部方法所示)。我打算在顶部方法if 语句中进行此检查,我认为这会起作用,但是,尽管velocityInView() 在底部方法中工作正常,但在顶部方法中却没有(速度始终为 0)。

我已经搜索了一些解决方案并找到了许多关于手势处理的类似查询,但这些查询似乎都与一种手势类型有关,例如捏,在一个视图和另一种类型,例如潘,另一方面。就我而言,两者的手势类型相同。

也许有人有一个聪明的主意?或者也许这实际上很简单,而我把它弄得非常复杂? xD

【问题讨论】:

    标签: ios swift uitableview uigesturerecognizer uipangesturerecognizer


    【解决方案1】:

    设法让这个工作。

    在我上面的问题中描述的方法中,我删除了最上面的方法,只保留了这个(它有一些变化):

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if ((gestureRecognizer as! UIPanGestureRecognizer).velocityInView(view).y < 0
            || pulloverVC.tableView.contentOffset.y > 0)
            && pulloverVC.view.frame.origin.y == bottomNavbarY {
                return true // enable tableview control
        }
        return false
    }
    

    if 语句检查覆盖UITableView 是否在其上方位置并且用户没有向下拖动表格内容偏移(我们不在表的顶部)。如果这是真的,那么我们return true 来启用tableview。

    调用此方法后,将调用为处理我的平移手势而实现的标准方法。在这里,我有一个 if 语句,它检查与上述相反的情况,如果这是真的,它会阻止对覆盖 viewB 的控制移动:

    func handlePanGesture(recognizer: UIPanGestureRecognizer) {
    
        let gestureIsDraggingFromTopToBottom = (recognizer.velocityInView(view).y > 0)
    
        if pulloverVC.view.frame.origin.y != bottomNavbarY || (pulloverVC.view.frame.origin.y == bottomNavbarY && gestureIsDraggingFromTopToBottom && pulloverVC.tableView.contentOffset.y == 0) {
    
        ...
    

    这会保持 UITableView 交互关闭,除非其父视图 viewB 处于正确位置,并且当它处于正确位置时,禁用 viewB 的移动,以便仅与 UITableView 交互有效。

    然后,当我们位于表格顶部并向下拖动时,与UITableView 的交互被重新禁用,而与其父视图viewB 的交互被重新启用。

    一个冗长的帖子和答案,但如果有人能理解我在说什么,希望它会帮助你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      相关资源
      最近更新 更多