Swift-UIPanGestureRecognizer仅在选择顶层时才选择所有层

时间:2019-03-06 01:09:59

标签: swift xcode uiview uipangesturerecognizer uiview-hierarchy

我具有创建拖动线以将2个按钮彼此连接的功能。这可以正常工作,但是如果某些按钮彼此重叠,则在我将它们重叠的地方拖移时会同时选择这两个按钮。我只想连接顶部按钮。

enter image description here

我认为问题出在顶部和下方的sender.location选择层。有没有办法告诉sender.location仅选择顶视图?感谢您的输入和指导

func addPanReconiser(view: UIView){

    let pan = UIPanGestureRecognizer(target: self, action: #selector(DesignViewController.panGestureCalled(_:)))
    view.addGestureRecognizer(pan)
}

@objc func panGestureCalled(_ sender: UIPanGestureRecognizer) {

    let currentPanPoint = sender.location(in: self.view)

    switch sender.state {
    case .began:

        panGestureStartPoint = currentPanPoint
        self.view.layer.addSublayer(lineShape)

    case .changed:
        let linePath = UIBezierPath()
        linePath.move(to: panGestureStartPoint)
        linePath.addLine(to: currentPanPoint)

        lineShape.path = linePath.cgPath
        lineShape.path = CGPath.barbell(from: panGestureStartPoint, to: currentPanPoint, barThickness: 2.0, bellRadius: 6.0)

        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point) {
                button.layer.borderWidth = 4
                button.layer.borderColor = UIColor.blue.cgColor
            } else {
                button.layer.borderWidth = 0
                button.layer.borderColor = UIColor.clear.cgColor
            }
        }

    case .ended:

        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point){

                //DO my Action here
                lineShape.path = nil
                lineShape.removeFromSuperlayer()

            }
        }
    default: break
    }
  }
}

注意:某些代码行来自自定义扩展。我把它们留在里面,因为它们很容易说明。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

有一种四处走动的方式。似乎您只是想让您的手势最终停留在所有其他按钮上方的一个按钮上,因此可以通过在循环外添加一个var并在每次选择按钮时将其与水平z处的var进行比较。

case .ended:
        var pickedButton: UIButton?
        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point){
                if pickedButton == nil {
                    pickedButton = button
                } else {
                    if let parent = button.superView, parent.subviews.firstIndex(of: button) > parent.subviews.firstIndex(of: pickedButton!) {
                        pickedButton = button
                    }
                }
            }
        }
        //DO my Action with pickedButton here
        lineShape.path = nil
        lineShape.removeFromSuperlayer()

答案 1 :(得分:0)

UIView具有名为subViews的属性,其中索引较高的元素在索引较低的元素之前。例如,索引为1的subView在索引为0的subView的前面。

话虽这么说,要获得位于顶部的按钮,您应该按照组织buttonArray的{​​{1}}属性的相同方式对subViews进行排序。假设您的按钮都是同一个UIView的兄弟姐妹(不一定是这种情况,但是您可以对其进行调整,以便对其进行正确排序):

UIView

因此,保持您的var buttonArray = view.subviews.compactMap { $0 as? UIButton } 那样的排序,您想要的按钮就是包含buttonArray且在数组中具有较高索引的按钮。