处理多个视图的 UIPanGestureRecognizer 手势(一个覆盖另一个)
Handling UIPanGestureRecognizer gestures for multiple Views (one covers the other)
抱歉问了这么长的问题,但我觉得我应该传达我的尝试。
我在导航控制器中有一个视图 viewA
。然后我将子视图 viewB
(包含 UITableView
)添加到 viewA
并偏移其原点高度,使其仅覆盖屏幕的一半(另一半从底部溢出)屏幕)。然后我希望能够向上拖动 viewB
但是当它到达导航栏的底部时它会停止,同样地当它到达原点偏移点时被向下拖动时会停止。这个我已经成功了。
但是,我希望 UITableView
交互仅在 viewB
处于其上方位置时启用,因此不响应任何其他位置的手势。从本质上讲,向上拖动 viewB
使其完全覆盖 viewA
应该可以与 UITableView
.
进行交互
这里棘手的部分是我希望它执行以下操作:
- 如果
viewB
位于其上方以覆盖屏幕,则 UITableView
内容偏移量为 0(即我们位于 table 的顶部)并且用户向下做出平移手势,该手势不应与 UITableView
交互,但应向下移动 viewB
。
- 上述情况下的任何其他平移手势都应该是与
UITableView
的交互。
- 如果
viewB
位于其上方以覆盖屏幕,则 UITableView
内容偏移量 NOT 为 0(即我们是NOT 在 table) 的顶部并且用户向下做出平移手势,该手势应该与 UITableView
. 交互
我已经非常接近实现这一目标,但我不能完全正确。
到目前为止的尝试次数
我正在使用 UIPanGestureRecognizer
来处理视图的拖动。我尝试将其添加到:
viewB
最初禁用 UITableView
用户交互。这允许我上下拖动 viewB
而不会干扰 UITableView
。一旦 viewB
处于其上方位置,我就会启用 UITableView
用户交互,这样我就可以在不移动 viewB
.
的情况下正确地与 UITableView
进行交互
但是,通过启用 UITableView
用户交互,这意味着触摸永远不会到达 UIPanGestureRecognizer
,这意味着我永远无法检测到上面第 (1.) 点中描述的场景,因此无法检测重新禁用 UITableView
用户交互以使 viewB
再次可移动。
也许可以通过覆盖 UITableView
使用的手势识别方法来做到这一点?如果这是可能的,谁能指出我正确的方向?
在UITableView
前面添加了一个新视图。我想也许我可以在必要时将触摸手势转发到它后面的UITableView
,但我仍然没有找到这样做的方法。
我所能做的就是禁用允许我与 UITableView
交互的手势识别器,但我遇到了与上述相同的问题。我无法检测到何时重新启用它。
viewB
中的 UITableView
。这似乎是迄今为止最有希望的方式。通过设置以下方法的 return 值,我可以启用和禁用对 viewB
和 UITableView
.
的识别
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
}
做出手势时首先调用顶部方法(我已经用打印语句检查过),然后是底部方法。通过对这两种方法进行 true/false 的不同组合,我可以在 viewB
和 UITableView
.
之间交替交互
为了检测用户是否向下滑动,我在识别器上调用 velocityInView()
(如底部方法所示)。我打算在顶部方法 if
语句中进行此检查,我认为这会起作用,但是,尽管 velocityInView()
在底部方法中工作正常,但在顶部方法中却没有(速度总是0).
我已经搜索了一些解决方案,并找到了许多关于手势处理的类似查询,这些视图相互覆盖,但这些似乎都与一种手势类型有关,例如捏,一种观点,另一种类型,例如平底锅,另一方面。在我的例子中,两者的手势类型相同。
也许有人有一个聪明的主意?或者也许这实际上很简单,但我却把它变得异常复杂? xD
设法让它工作。
在我上面的问题中描述的方法中,我删除了最上面的方法,只保留了这个(它有一些变化):
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
是否在其上部位置 并且 用户没有向下拖动 或 的table 内容是偏移量(我们不是在table 的顶部)。如果这是真的,那么我们 return true
启用 table 视图。
调用此方法后,将调用为处理我的平移手势而实现的标准方法。在这里我有一个 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) {
...
现在,除非其父视图 viewB
处于正确的位置,否则这会关闭 UITableView
交互,并且当它处于正确位置时,禁用 viewB
的移动,以便仅与UITableView
有效。
然后,当我们位于 table 的顶部并向下拖动时,将重新禁用与 UITableView
的交互,并重新禁用与其父视图 viewB
的交互-启用。
罗嗦post然后回答,但如果有人能理解我在说什么,希望对你有所帮助。
抱歉问了这么长的问题,但我觉得我应该传达我的尝试。
我在导航控制器中有一个视图 viewA
。然后我将子视图 viewB
(包含 UITableView
)添加到 viewA
并偏移其原点高度,使其仅覆盖屏幕的一半(另一半从底部溢出)屏幕)。然后我希望能够向上拖动 viewB
但是当它到达导航栏的底部时它会停止,同样地当它到达原点偏移点时被向下拖动时会停止。这个我已经成功了。
但是,我希望 UITableView
交互仅在 viewB
处于其上方位置时启用,因此不响应任何其他位置的手势。从本质上讲,向上拖动 viewB
使其完全覆盖 viewA
应该可以与 UITableView
.
这里棘手的部分是我希望它执行以下操作:
- 如果
viewB
位于其上方以覆盖屏幕,则UITableView
内容偏移量为 0(即我们位于 table 的顶部)并且用户向下做出平移手势,该手势不应与UITableView
交互,但应向下移动viewB
。 - 上述情况下的任何其他平移手势都应该是与
UITableView
的交互。 - 如果
viewB
位于其上方以覆盖屏幕,则UITableView
内容偏移量 NOT 为 0(即我们是NOT 在 table) 的顶部并且用户向下做出平移手势,该手势应该与UITableView
. 交互
我已经非常接近实现这一目标,但我不能完全正确。
到目前为止的尝试次数
我正在使用 UIPanGestureRecognizer
来处理视图的拖动。我尝试将其添加到:
的情况下正确地与viewB
最初禁用UITableView
用户交互。这允许我上下拖动viewB
而不会干扰UITableView
。一旦viewB
处于其上方位置,我就会启用UITableView
用户交互,这样我就可以在不移动viewB
.UITableView
进行交互但是,通过启用
UITableView
用户交互,这意味着触摸永远不会到达UIPanGestureRecognizer
,这意味着我永远无法检测到上面第 (1.) 点中描述的场景,因此无法检测重新禁用UITableView
用户交互以使viewB
再次可移动。也许可以通过覆盖
UITableView
使用的手势识别方法来做到这一点?如果这是可能的,谁能指出我正确的方向?在
UITableView
前面添加了一个新视图。我想也许我可以在必要时将触摸手势转发到它后面的UITableView
,但我仍然没有找到这样做的方法。我所能做的就是禁用允许我与
UITableView
交互的手势识别器,但我遇到了与上述相同的问题。我无法检测到何时重新启用它。
的识别viewB
中的UITableView
。这似乎是迄今为止最有希望的方式。通过设置以下方法的 return 值,我可以启用和禁用对viewB
和UITableView
.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 }
做出手势时首先调用顶部方法(我已经用打印语句检查过),然后是底部方法。通过对这两种方法进行 true/false 的不同组合,我可以在
之间交替交互viewB
和UITableView
.为了检测用户是否向下滑动,我在识别器上调用
velocityInView()
(如底部方法所示)。我打算在顶部方法if
语句中进行此检查,我认为这会起作用,但是,尽管velocityInView()
在底部方法中工作正常,但在顶部方法中却没有(速度总是0).
我已经搜索了一些解决方案,并找到了许多关于手势处理的类似查询,这些视图相互覆盖,但这些似乎都与一种手势类型有关,例如捏,一种观点,另一种类型,例如平底锅,另一方面。在我的例子中,两者的手势类型相同。
也许有人有一个聪明的主意?或者也许这实际上很简单,但我却把它变得异常复杂? xD
设法让它工作。
在我上面的问题中描述的方法中,我删除了最上面的方法,只保留了这个(它有一些变化):
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
是否在其上部位置 并且 用户没有向下拖动 或 的table 内容是偏移量(我们不是在table 的顶部)。如果这是真的,那么我们 return true
启用 table 视图。
调用此方法后,将调用为处理我的平移手势而实现的标准方法。在这里我有一个 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) {
...
现在,除非其父视图 viewB
处于正确的位置,否则这会关闭 UITableView
交互,并且当它处于正确位置时,禁用 viewB
的移动,以便仅与UITableView
有效。
然后,当我们位于 table 的顶部并向下拖动时,将重新禁用与 UITableView
的交互,并重新禁用与其父视图 viewB
的交互-启用。
罗嗦post然后回答,但如果有人能理解我在说什么,希望对你有所帮助。