在激活UIView时点击手势

时间:2022-03-09 08:41:51

I have a tap gesture on a UILabel who's translation is being animated. Whenever you tap on the label during the animation there's no response from the tap gesture.

我在UILabel上做了一个轻击手势,她的翻译是动画的。当你在动画中点击标签时,点击手势没有反应。

Here's my code:

这是我的代码:

    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)

Gesture code:

手势代码:

func setUpRecognizers() {
    tapGesture = UITapGestureRecognizer(target: self, action: "onTap:")
}
func onTap(sender : AnyObject) {
    print("Tapped")
}

Any ideas? Thanks :)

什么好主意吗?谢谢:)

4 个解决方案

#1


2  

You will not be able to accomplish what you are after using a tapgesture for 1 huge reason. The tapgesture is associated with the frame of the label. The labels final frame is changed instantly when kicking off the animation and you are just watching a fake movie(animation). If you were able to touch (0,900) on the screen it would fire as normal while the animation is occuring. There is a way to do this a little bit different though. The best would be to uses touchesBegan. Here is an extension I just wrote to test my theory but could be adapted to fit your needs.For example you could use your actual subclass and access the label properties without the need for loops.

由于一个巨大的原因,在使用tap手势之后,你将无法完成你的目标。tap手势与标签的框架相关联。当开始动画时,标签的最终帧会立即改变,而你只是在看一个假电影(动画)。如果你能触摸屏幕上的(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
                    })
                })
            }
        }

    }
}

You can see that it is testing the coordinates of the CALayer.presentationLayer()..That's what I was calling the movies. To be honest, I have still not wrapped my head completely around the presentation layer and how it works.

您可以看到它正在测试CALayer.presentationLayer()的坐标。这就是我所谓的电影。老实说,我还没有完全把我的头脑和它是如何工作的。

#2


0  

For your tap gesture to work, you have to set the number of taps. Add this line:

要让你的轻拍动作生效,你必须设置轻拍的次数。添加这一行:

tapGesture.numberOfTapsRequired = 1

tapGesture。numberOfTapsRequired = 1

(I'm assuming that tapGesture is the same one you call label.addGestureRecognizer(tapGesture) with)

(我假设tapGesture (tap手势)和label.addGestureRecognizer(tap手势)是一样的)

#3


0  

If you want to see the animation, you need to put it in the onTap handler.

如果想要看到动画,需要将其放入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")
}

#4


0  

Below is a more generic answer based on the answer from @agibson007 in Swift 3.

以下是基于Swift 3中@agibson007的答案的更一般的答案。

This didn't solve my issue immediately, because I had additional subviews covering my view. If you have trouble, try changing the extension type and writing print statements for touchLocation to find out when the function is firing. The description in the accepted answer explains the issue well.

这并不能立即解决我的问题,因为我有其他的子视图来覆盖我的视图。如果有问题,请尝试更改扩展类型并为touchLocation编写打印语句,以查明函数何时触发。在公认答案中的描述很好地解释了这个问题。

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

            }

        }

    }

}

#1


2  

You will not be able to accomplish what you are after using a tapgesture for 1 huge reason. The tapgesture is associated with the frame of the label. The labels final frame is changed instantly when kicking off the animation and you are just watching a fake movie(animation). If you were able to touch (0,900) on the screen it would fire as normal while the animation is occuring. There is a way to do this a little bit different though. The best would be to uses touchesBegan. Here is an extension I just wrote to test my theory but could be adapted to fit your needs.For example you could use your actual subclass and access the label properties without the need for loops.

由于一个巨大的原因,在使用tap手势之后,你将无法完成你的目标。tap手势与标签的框架相关联。当开始动画时,标签的最终帧会立即改变,而你只是在看一个假电影(动画)。如果你能触摸屏幕上的(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
                    })
                })
            }
        }

    }
}

You can see that it is testing the coordinates of the CALayer.presentationLayer()..That's what I was calling the movies. To be honest, I have still not wrapped my head completely around the presentation layer and how it works.

您可以看到它正在测试CALayer.presentationLayer()的坐标。这就是我所谓的电影。老实说,我还没有完全把我的头脑和它是如何工作的。

#2


0  

For your tap gesture to work, you have to set the number of taps. Add this line:

要让你的轻拍动作生效,你必须设置轻拍的次数。添加这一行:

tapGesture.numberOfTapsRequired = 1

tapGesture。numberOfTapsRequired = 1

(I'm assuming that tapGesture is the same one you call label.addGestureRecognizer(tapGesture) with)

(我假设tapGesture (tap手势)和label.addGestureRecognizer(tap手势)是一样的)

#3


0  

If you want to see the animation, you need to put it in the onTap handler.

如果想要看到动画,需要将其放入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")
}

#4


0  

Below is a more generic answer based on the answer from @agibson007 in Swift 3.

以下是基于Swift 3中@agibson007的答案的更一般的答案。

This didn't solve my issue immediately, because I had additional subviews covering my view. If you have trouble, try changing the extension type and writing print statements for touchLocation to find out when the function is firing. The description in the accepted answer explains the issue well.

这并不能立即解决我的问题,因为我有其他的子视图来覆盖我的视图。如果有问题,请尝试更改扩展类型并为touchLocation编写打印语句,以查明函数何时触发。在公认答案中的描述很好地解释了这个问题。

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

            }

        }

    }

}