我在UILabel上有一个轻击手势,其翻译正在动画中。每当您在动画期间点击标签时,点击手势都没有响应。
这是我的代码:
label.addGestureRecognizer(tapGesture)
label.userInteractionEnabled = true
label.transform = CGAffineTransformMakeTranslation(0, 0)
UIView.animateWithDuration(12, delay: 0, options: UIViewAnimationOptions.AllowUserInteraction, animations: { () -> Void in
label.transform = CGAffineTransformMakeTranslation(0, 900)
}, completion: nil)
手势代码:
func setUpRecognizers() {
tapGesture = UITapGestureRecognizer(target: self, action: "onTap:")
}
func onTap(sender : AnyObject) {
print("Tapped")
}
有什么想法吗?谢谢:))
答案 0 :(得分:2)
由于一个重要原因,您使用tapgesture后将无法完成您的目标。 tapgesture与标签的框架相关联。开始动画时,标签最终帧会立即更改,而您正在观看假电影(动画)。如果您能够在屏幕上触摸(0,900),则会在动画发生时正常触发。有一种方法可以做到这一点有点不同。最好的是使用touchesBegan。这是我刚刚编写的用于测试我的理论的扩展,但可以根据您的需要进行调整。例如,您可以使用实际的子类并访问标签属性而无需循环。
extension UIViewController{
public override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touch = touches.first else{return}
let touchLocation = touch.locationInView(self.view)
for subs in self.view.subviews{
guard let ourLabel = subs as? UILabel else{return}
print(ourLabel.layer.presentationLayer())
if ourLabel.layer.presentationLayer()!.hitTest(touchLocation) != nil{
print("Touching")
UIView.animateWithDuration(0.4, animations: {
self.view.backgroundColor = UIColor.redColor()
}, completion: {
finished in
UIView.animateWithDuration(0.4, animations: {
self.view.backgroundColor = UIColor.whiteColor()
}, completion: {
finished in
})
})
}
}
}
}
你可以看到它正在测试CALayer.presentationLayer()的坐标。这就是我所说的电影。说实话,我仍然没有完全围绕表示层及其工作方式。
答案 1 :(得分:2)
我在这个问题上呆了好几个小时,不明白为什么点击不能在动画标签上起作用,而动画标签会在延迟3秒后滑出屏幕。
好说agibson007,关于动画的工作方式就像是假电影的播放,延迟3秒控制了电影的回报,但是动画一开始就没有延迟就改变了标签的帧。因此,点击(取决于标签在其原始位置的框架)将无法工作。
我的解决方案是将3秒延迟更改为超时功能,例如-
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
[weak self] in
self?.hideLabel()
}
这样可以在延迟期间保持轻拍工作,并允许在延迟之后在hideLabel()调用中运行动画。
答案 2 :(得分:1)
如果要查看动画,则需要将其放在onTap处理程序中。
let gesture = UITapGestureRecognizer(target: self, action: "onTap:")
gesture.numberOfTapsRequired = 1
label.addGestureRecognizer(gesture)
label.userInteractionEnabled = true
label.transform = CGAffineTransformMakeTranslation(0, 0)
UIView.animateWithDuration(12, delay: 3, options: [.AllowUserInteraction], animations: { () -> Void in
label.transform = CGAffineTransformMakeTranslation(0, 900)
}, completion: nil)
func onTap(sender : AnyObject)
{
print("Tapped")
}
答案 3 :(得分:0)
要使您的点按手势有效,您必须设置点击次数。添加以下行:
tapGesture.numberOfTapsRequired = 1
(我假设tapGesture
与您调用的label.addGestureRecognizer(tapGesture)
相同
答案 4 :(得分:0)
以下是基于Swift 3中@ agibson007答案的更通用的答案。
这并没有立即解决我的问题,因为我有其他子视图覆盖了我的观点。如果遇到问题,请尝试更改扩展类型并为touchLocation
编写print语句,以找出函数何时触发。接受的答案中的描述很好地解释了这个问题。
extension UIViewController {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let touchLocation = touch.location(in: self.view)
for subview in self.view.subviews {
if subview.tag == VIEW_TAG_HERE && subview.layer.presentation()?.hitTest(touchLocation) != nil {
print("[UIViewController] View Touched!")
// Handle Action Here
}
}
}
}
答案 5 :(得分:0)
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pf = layer.presentation()!.frame
// note, that is in the space of our superview
let p = self.convert(point, to: superview!)
if pf.contains(p) { return self }
return nil
}
相关提示-
不要忘记,在大多数情况下,如果正在运行动画,则几乎可以肯定要取消它。因此,假设有一个“移动目标”,并且您希望能够用手指抓住它并将其滑动到其他位置,那么在这种情况下,视图控制器中的代码自然就像..
func sliderTouched() {
if alreadyMoving {
yourPropertyAnimator?.stopAnimation(true)
yourPropertyAnimator = nil
}
etc ...
}