简体   繁体   中英

UIButton touch location inaccurate when UIView Animating/Rotating

在此处输入图片说明

Hello all you awesome peeps! I have been having an odd issue where if UIView is animated, in my case rotated, during the animation the subviews touch locations are inaccurate.

For example, if I keep clicking button1, sometimes button2 will be pressed or nothing will be pressed. I've searched on STO and other blogs, trying their methods, but nothing seems to work. My goal is to have buttons clickable when the view is rotating.

I thought it was a UIButton bug or issue, but even with imageViews, and touch delegates or added Gestures, I get the same thing. I feel like something simple, like the presentation.layer or something that needs to be added to the UIView animate function, but I'm kinda at a loss. Hope you can shed some insight! Thank you all in advance.

func updateRotateView () 
{
    UIView.animateWithDuration(2,
        delay: 0.0,
        options: [UIViewAnimationOptions.CurveLinear, UIViewAnimationOptions.AllowUserInteraction],
        animations: {
            self.rotationView.transform = CGAffineTransformRotate(self.rotationView.transform, 3.1415926)

             //Test A
             //self.button1.frame = self.rotationView.convertRect(self.button1.frame, fromView:self.rotationView)
             //self.button1.layer.frame = self.rotationView.layer.convertRect(self.button1.layer.frame, fromLayer: self.rotationView.layer)
        }
     completion: {finished in })
 }


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
{
    //Test B
    let firstTouch = touches.first
    let firstHitPoint = firstTouch.locationInView(self.rotationView)

    if (self.button1.frame.contains(firstHitPoint)) {
        print("Detected firstHit on Button1")
    }

    if (self.button1.layer.frame.contains(firstHitPoint)) {
        print("Detected firstHit on Button1.layer")
    }

    if ((self.button1.layer.presentationLayer()?.hitTest(firstHitPoint!)) != nil) {
        print("Detected button1.layer hit test")
    }
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    //Test C
    let lastTouch = touches.first!
    let lastHitPoint = lastTouch.locationInView(self.rotationView)

    if (self.button1.frame.contains(lastHitPoint)) {
        print("Detected lastHit on Button1")
    }

    if (self.button1.layer.frame.contains(lastHitPoint)) {
        print("Detected lastHit on Button1.layer")
    }

    if ((self.button1.layer.presentationLayer()?.hitTest(lastHitPoint!)) != nil) {
        print("Detected button1.layer hit test")
    }
}

extension UIButton {
    //Test D
    public override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? 
     {
        print("hitTest called")
     }

    public override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool 
     {
        print("pointInside called")
     }
}

Test A -> rotationView.presentationLayer value changes, but the buttons do not, and setting it to an updated frame, is not working as the button1 frame or layer.frame size values do not change.

Test B/C -> UIButton does not respond to touch delegates, but even with imageViews does not hit accurately. Also did try Gestures with same result.

Test D -> Hitpoint does get called, but most likely on the wrong button as well. Point inside only gets called few times and if I am able to press the correct button, but again very inaccurate.

Because you are animating a view. You should know that there is a presentation layer and a model layer when animating.

Once self.rotationView.transform = CGAffineTransformRotate(self.rotationView.transform, 3.1415926) is called in the animation block, the transform of rotationView has already been set, and the animation you see is just the presentation layer(It is an id type but it should be CALayer).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM