bringSubviewToFront(_:) 函数破坏了 UIPanGestureRecognizer

Posted

技术标签:

【中文标题】bringSubviewToFront(_:) 函数破坏了 UIPanGestureRecognizer【英文标题】:bringSubviewToFront(_:) function breaks a UIPanGestureRecognizer 【发布时间】:2016-01-04 19:34:32 【问题描述】:

我有一个BoardView 类,它是UIView 的子类。它有几个子视图,它们都有自己的UIPanGestureRecognizer。我使用这个识别器在我的BoardView 实例中拖动子视图,如下所示:

func pieceDragged(recognizer: UIPanGestureRecognizer) 
    let pieceView = recognizer.view!
    if recognizer.state == .Began || recognizer.state == .Changed 
        // move the pieceView by the appropriate amount
        let translation = recognizer.translationInView(self)
        pieceView.center = CGPoint(x: pieceView.center.x + translation.x, y: pieceView.center.y + translation.y)
        recognizer.setTranslation(CGPoint.zero, inView: self)
     else if recognizer.state == .Ended 
        // do something else
    

这很好用。

问题是我希望被拖动的子视图位于所有兄弟视图之上,因此我将 BoardView 实例设为每个手势识别器的委托并覆盖此函数:

override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool 
    let pieceView = gestureRecognizer.view!
    bringSubviewToFront(pieceView)
    return true

这似乎破坏了整个手势识别器:如果我尝试拖动子视图,pieceDragged(_:) 函数将被调用一次(识别器的状态为.Began),但仅此而已。

如果我注释掉 bringSubviewToFront(pieceView),我的代码会像以前一样工作 - 我可以拖动任何子视图,但它位于它的一些兄弟视图之下。

我一无所知。这里会发生什么?

【问题讨论】:

我刚刚重新创建了一个简单的BoardView 类,使用与您相同的两个完全相同的方法,它工作正常。这节课还有其他内容吗? 【参考方案1】:

问题是我替换了layoutSubviews() 方法中的所有子视图(在调用bringToFront(_:) 后自动调用)。

【讨论】:

虽然我可以看到这是程序员的错误,但很好地发布了这个并回答。我遇到了同样的问题,也有奇怪的行为,只是在我没想到时才意识到 layoutSubviews() 被调用了。【参考方案2】:

似乎您也在四处走动并实施一种没有真正意义的方法。委托方法gestureRecognizerShouldBegin(_:) 是关于这个识别器是否真正开始检测到不是执行操作的地方。

你已经有一个合适的地方来执行你想要的操作,你可以简单地更新你的代码

func pieceDragged(recognizer: UIPanGestureRecognizer) 
  guard let pieceView = recognizer.view else 
    return
  

  switch recognizer.state 
  case .Began:
    pieceView.superview?.bringSubviewToFront(pieceView)

  case .Changed:
    let translation = recognizer.translationInView(self)
    recognizer.setTranslation(CGPoint.zero, inView: self)

    pieceView.center = CGPoint(x: pieceView.center.x + translation.x, y: pieceView.center.y + translation.y)

  default: ()
  

【讨论】:

我把那行代码放在gestureRecognizerShouldBegin(_:)中,因为它只需要执行一次,而且每次移动手指都会调用pieceDragged(_:)函数。无论如何,我尝试按照您的建议将其放入该函数中,但问题仍然存在。 我已经更新了它,所以它只会调用一次bringToFront(_:)。现在看看我原来的评论 - 你粘贴的代码在我的新项目中运行良好,你还在做什么吗? 我开始把事情注释掉,看看哪里出了问题,结果我调用了一个函数,在该函数中我从 layoutSubviews() 方法中布局了所有子视图,依次调用了每个时间我把一个子视图带到前面。直到我设置了一个断点,我才意识到这发生了。 您对如何解决这个问题有什么建议吗?一旦调用了layoutSubviews(),我就会失去对pieceView 的引用(因为我通过删除所有pieceViews 并用新的替换它们来布局我的子视图)。 为什么要全部删除和添加?

以上是关于bringSubviewToFront(_:) 函数破坏了 UIPanGestureRecognizer的主要内容,如果未能解决你的问题,请参考以下文章

bringSubviewToFront 将 UIView 移回原始位置

在 Ipad 滚动视图中使用bringSubviewToFront

bringSubviewToFront 不适用于下拉视图(UIView)

我将如何为bringSubviewToFront 编写 UIView 淡入动画

viewDidLoad() 中的 addSubView() 和 bringSubViewToFront() 不起作用

UIView bringSubviewToFront: *不*将视图带到前面