I'm doing an animation like this:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.duration = 100.0;
animation.path = self.animationPath.CGPath;
[view.layer addAnimation:animation forKey:@"animation"];
Works fine, however, this now fails when trying to detect touches on the object that is moving around the screen:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for (UIView* subview in self.subviews ) {
if ( [subview hitTest:[self convertPoint:point toView:subview] withEvent:event] != nil ) {
[self handleTap];
return YES;
}
}
return NO;
}
It fails because the view's frame is no longer the same as it's apparent position on the screen when it is being animated. How can I get pointInside
to work with a view that is being animated?
Short answer: You can't. In both UIView and Core Animation animations, the view/layer does not actually move as it's position appears to be animating. Instead, there is a "presentation layer" that draws the animated object as it moves.
If you want to make objects tappable while a position animation is "in flight" you have to put a tap gesture recognizer on a superview that spans the entire area the view will travel over, and then do hit testing on the presentation layer of the object that's being animated.
Edit:
I have a project on Github called iOS CAAnimation Group demo that is a working demonstration of how to use hit testing on the presentation layer to detect taps on a view that's being animated along a complex path.
The code is written in Objective-C, but it should still be an illustration of the concept and techniques. Let me know if you have trouble making sense of the Objective-C code. I'm decent at Swift, although I'm still paying the bills in mostly Objective-C, so that's the syntax I know best.
This is my code to do this
I hope this helps you