Swift - UIPanGestureRecognizer 在只想选择顶层时选择所有层
Swift - UIPanGestureRecognizer selecting all layers when only want the top layer selected
我有创建拖线以将 2 个按钮相互连接的功能。这工作正常,但如果一些按钮相互重叠,如果我拖动它们重叠的地方,它会 select 两者。我只想连接顶部按钮。
我认为问题出在顶部和底部的 sender.location selecting 层上。有没有办法告诉 sender.location 仅 select 顶视图?感谢您的任何意见和指导
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
}
}
}
注意:部分代码行来自自定义扩展。我保留了它们,因为它们不言自明。
感谢您的帮助
A UIView
有一个名为 subViews
的 属性,其中索引较高的元素位于索引较低的元素之前。例如,索引为 1 的子视图在索引为 0 的子视图之前。
也就是说,要获得顶部的按钮,您应该按照 UIView
的 subViews
属性 的相同方式对 buttonArray
进行排序。假设您的按钮都是同一个 UIView
的同级按钮(情况可能不一定如此,但您可以调整它们以便正确排序):
var buttonArray = view.subviews.compactMap { [=10=] as? UIButton }
因此,保持您的 buttonArray
排序,您想要的按钮是包含数组中具有更高索引的 let point = sender.location(in: button)
的按钮。
有路可走。看起来你只是希望你的手势在所有其他按钮之上的一个按钮结束,因此通过在循环外添加一个 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()
我有创建拖线以将 2 个按钮相互连接的功能。这工作正常,但如果一些按钮相互重叠,如果我拖动它们重叠的地方,它会 select 两者。我只想连接顶部按钮。
我认为问题出在顶部和底部的 sender.location selecting 层上。有没有办法告诉 sender.location 仅 select 顶视图?感谢您的任何意见和指导
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
}
}
}
注意:部分代码行来自自定义扩展。我保留了它们,因为它们不言自明。
感谢您的帮助
A UIView
有一个名为 subViews
的 属性,其中索引较高的元素位于索引较低的元素之前。例如,索引为 1 的子视图在索引为 0 的子视图之前。
也就是说,要获得顶部的按钮,您应该按照 UIView
的 subViews
属性 的相同方式对 buttonArray
进行排序。假设您的按钮都是同一个 UIView
的同级按钮(情况可能不一定如此,但您可以调整它们以便正确排序):
var buttonArray = view.subviews.compactMap { [=10=] as? UIButton }
因此,保持您的 buttonArray
排序,您想要的按钮是包含数组中具有更高索引的 let point = sender.location(in: button)
的按钮。
有路可走。看起来你只是希望你的手势在所有其他按钮之上的一个按钮结束,因此通过在循环外添加一个 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()