检测动画 UIImageView 上的点击
Detecting taps on an animating UIImageView
我在 Swift 3 项目的 UIImageView 项目上使用自定义路径动画。代码大纲如下:
// parentView and other parameters are configured externally
let imageView = UIImageView(image: image)
imageView.isUserInteractionEnabled = true
let gr = UITapGestureRecognizer(target: self, action: #selector(onTap(gesture:)))
parentView.addGestureRecognizer(gr)
parentView.addSubview(imageView)
// Then I set up animation, including:
let animation = CAKeyframeAnimation(keyPath: "position")
// .... eventually ....
imageView.layer.add(animation, forKey: nil)
onTap方法以标准方式声明:
func onTap(gesture:UITapGestureRecognizer) {
print("ImageView frame is \(self.imageView.layer.visibleRect)")
print("Gesture occurred at \(gesture.location(in: FloatingImageHandler.parentView))")
}
问题是每次我调用 addGestureRecognizer 时,之前的手势识别器都会被覆盖,所以任何检测到的点击总是指向最后添加的图像,并且无法准确检测到位置(所以如果有人点击 parentView 上的任何地方,它仍然会触发 onTap 方法。
如何在每个图像视图的基础上准确检测点击?由于自定义路径动画要求,我无法使用 UIView.animate 或其他方法,而且我也无法创建覆盖透明 UIView 来覆盖父视图,因为我需要这些 "floaters" 不吞下事件。
不太清楚您要实现什么,但我认为您应该将手势识别器添加到 imageView 而不是 parentView。
所以这个:
parentView.addGestureRecognizer(gr)
应替换为:
imageView.addGestureRecognizer(gr)
在您的 onTap 函数中,您可能应该这样做:
print("ImageView frame is \(gesture.view.layer.visibleRect)")
print("Gesture occurred at \(gesture.location(in: gesture.view))")
我想你可以在 onTap
功能上检查属于 imageView
或不属于 onTap
的抽头位置。
像这样:
func ontap(gesture:UITapGestureRecognizer) {
let point = gesture.location(in: parentView)
if imageView.layer.frame.contains(point) {
print("ImageView frame is \(self.imageView.layer.visibleRect)")
print("Gesture occurred at \(point)")
}
}
由于图层不更新它们的 frame/position 等,我需要在我编写的图像视图子类中添加以下内容 (FloatingImageView
):
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
let prespt = self.superview!.layer.convert(suppt, to: pres)
return super.hitTest(prespt, with: event)
}
我还将手势识别器移到了父视图中,因此任何时候都只有一个 GR,并为添加的每个子视图创建了一个唯一的标签。处理程序如下所示:
func onTap(gesture:UITapGestureRecognizer) {
let p = gesture.location(in: gesture.view)
let v = gesture.view?.hitTest(p, with: nil)
if let v = v as? FloatingImageView {
print("The tapped view was \(v.tag)")
}
}
其中 FloatingImageView
是 UIImageView
子类。
此方法在 iOS 10 本书(以及 WWDC)中有所描述,也适用于 iOS 9。我仍在评估基于 UIViewPropertyAnimator
的敲击检测,因此如果您能给我一个如何使用 UIViewPropertyAnimator
执行上述操作的示例,我会将您的答案标记为正确答案。
我在 Swift 3 项目的 UIImageView 项目上使用自定义路径动画。代码大纲如下:
// parentView and other parameters are configured externally
let imageView = UIImageView(image: image)
imageView.isUserInteractionEnabled = true
let gr = UITapGestureRecognizer(target: self, action: #selector(onTap(gesture:)))
parentView.addGestureRecognizer(gr)
parentView.addSubview(imageView)
// Then I set up animation, including:
let animation = CAKeyframeAnimation(keyPath: "position")
// .... eventually ....
imageView.layer.add(animation, forKey: nil)
onTap方法以标准方式声明:
func onTap(gesture:UITapGestureRecognizer) {
print("ImageView frame is \(self.imageView.layer.visibleRect)")
print("Gesture occurred at \(gesture.location(in: FloatingImageHandler.parentView))")
}
问题是每次我调用 addGestureRecognizer 时,之前的手势识别器都会被覆盖,所以任何检测到的点击总是指向最后添加的图像,并且无法准确检测到位置(所以如果有人点击 parentView 上的任何地方,它仍然会触发 onTap 方法。
如何在每个图像视图的基础上准确检测点击?由于自定义路径动画要求,我无法使用 UIView.animate 或其他方法,而且我也无法创建覆盖透明 UIView 来覆盖父视图,因为我需要这些 "floaters" 不吞下事件。
不太清楚您要实现什么,但我认为您应该将手势识别器添加到 imageView 而不是 parentView。
所以这个:
parentView.addGestureRecognizer(gr)
应替换为:
imageView.addGestureRecognizer(gr)
在您的 onTap 函数中,您可能应该这样做:
print("ImageView frame is \(gesture.view.layer.visibleRect)")
print("Gesture occurred at \(gesture.location(in: gesture.view))")
我想你可以在 onTap
功能上检查属于 imageView
或不属于 onTap
的抽头位置。
像这样:
func ontap(gesture:UITapGestureRecognizer) {
let point = gesture.location(in: parentView)
if imageView.layer.frame.contains(point) {
print("ImageView frame is \(self.imageView.layer.visibleRect)")
print("Gesture occurred at \(point)")
}
}
由于图层不更新它们的 frame/position 等,我需要在我编写的图像视图子类中添加以下内容 (FloatingImageView
):
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
let prespt = self.superview!.layer.convert(suppt, to: pres)
return super.hitTest(prespt, with: event)
}
我还将手势识别器移到了父视图中,因此任何时候都只有一个 GR,并为添加的每个子视图创建了一个唯一的标签。处理程序如下所示:
func onTap(gesture:UITapGestureRecognizer) {
let p = gesture.location(in: gesture.view)
let v = gesture.view?.hitTest(p, with: nil)
if let v = v as? FloatingImageView {
print("The tapped view was \(v.tag)")
}
}
其中 FloatingImageView
是 UIImageView
子类。
此方法在 iOS 10 本书(以及 WWDC)中有所描述,也适用于 iOS 9。我仍在评估基于 UIViewPropertyAnimator
的敲击检测,因此如果您能给我一个如何使用 UIViewPropertyAnimator
执行上述操作的示例,我会将您的答案标记为正确答案。