我有一个UIView
可以填满整个屏幕,然后在该容器视图中添加多个小圆圈UIView
,我希望可以使用UIPanGestureRecognizer
拖动这些小圆圈的UIView 。但是有时它们碰巧彼此重叠,使得顶部的UIView根本无法单击,它总是选择底部的UIView。
在容器UIView中,我实现了hitTest
以仅选择那些子视图。
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
}
我怎样才能使顶视图获得点击,而不是底视图?
答案 0 :(得分:1)
我通过创建UIView子类,添加UIPanGestureRecognizer并根据其输入进行更新来处理可拖动视图。
使用此方法,无论哪个视图位于顶部,都将获得触摸效果,而您不必覆盖超级视图上的docker image prune
。
我还添加了一个委托,以在视图限于超级视图时更新约束。通过设置委托,UIView或ViewController(以委托为准)可以更新要移动的视图的约束。
这是一个简单的实现:
hitTest
这是我使用此视图在视图控制器中实现委托回调的方式,因为我的视图使用了约束:
// 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)
}
}