我有一个填满整个屏幕的 UIView
,然后我在该容器 View 中添加了多个小圆圈 UIView
,我希望这些小圆圈的 UIView 可以拖动使用 UIPanGestureRecognizer
。但有时它们恰好在彼此之上,使得顶部的 UIView 根本不可点击,它总是选择底部的。
在容器 UIView 中,我实现了 hitTest
以便能够仅选择那些 subview 。
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
for planet in self.myPlanets.values {
if let presentation = planet.layer.presentation(), presentation.frame.contains(point) {
return planet
}
}
return nil
}
如何让顶部 View 接收点击而不是底部 View ?
最佳答案
我通过创建 UIView 子类、添加 UIPanGestureRecognizer 并根据其输入进行更新来处理可拖动 View 。
使用此方法,无论哪个 View 在顶部都会接收到触摸,并且您不必覆盖父 View 上的 hitTest
。
如果 View 受限于父 View ,我还添加了一个委托(delegate)来更新约束。通过设置委托(delegate),UIView 或 ViewController(以委托(delegate)为准)可以更新要移动的 View 的约束。
这是一个简单的实现:
// Delegate protocol for managing constraint updates if needed
protocol DraggableDelegate: class {
// tells the delegate to move
func moveByTranslation(_ change: CGPoint)
}
class DraggableView: UIView {
var dragDelegate: DraggableDelegate?
init() {
// frame is set later if needed by creator
super.init(frame: CGRect.zero)
configureGestureRecognizers()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// setup UIPanGestureRecognizer
internal func configureGestureRecognizers() {
let panGR = UIPanGestureRecognizer.init(target: self, action: #selector(didPan(_:)))
addGestureRecognizer(panGR)
}
@objc func didPan(_ panGR: UIPanGestureRecognizer) {
// get the translation
let translation = panGR.translation(in: self).applying(transform)
if let delegate = dragDelegate {
// tell delegate to move
delegate.moveByTranslation(translation)
} else {
// move self
self.center.x += translation.x
self.center.y += translation.y
}
// reset translation
panGR.setTranslation(CGPoint.zero, in: self)
}
}
下面是我如何使用这个 View 在 View Controller 中实现委托(delegate)回调,因为我的 View 使用了约束:
/// Moves the tool tray when dragging is triggered via the pan gesture recognizer in the tool tray (an instance of DraggableView).
///
/// - Parameter change: The x/y change provided by the pan gesture recognizer.
func moveByTranslation(_ change: CGPoint) {
// only interested in the y axis movements for this example
// update the constraint that moves this view
let newPos = constraint_tooltray_yAxis.constant + change.y
// this function limited the movement of the view to keep it within bounds
updateToolTrayPosition(newPos)
}
关于ios - 当多个 UIView 相互重叠时,甚至在顶部 UIView 上拦截点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51974299/