在UIView动画期间阻止用户输入

时间:2011-04-21 18:36:57

标签: iphone cocoa-touch ios uiviewanimation

我有一个UIView动画(由touchesEnded:事件调用),我希望在允许更多用户输入之前完成执行。在调用动画之前,我检查标志“isMoving”以查看动画是否正在进行中。然后我将isMoving设置为YES并按如下方式执行动画(是的,我知道它不是块格式的)...

- (void) methodCalledFromViewControllerTouchesEnded {
    if (isMoving == YES) {
        NSLog (@"Don't start another animation!");
        return;
    }   
    isMoving = YES;

    ......

    [UIView beginAnimations:@"move" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:0.25f];
    ...
    // DO MOVE STUFF
    ...
    [UIView commitAnimations];

    isMoving = NO;
}

然后我将isMoving设置为NO,以便来自touchesEnded:的后续调用在当前正在进行时不会启动另一个动画。但是,如果用户在初始动画进行过程中一直保持触摸,则此 FAILS 和动画会重复进行。

我想知道这是否可能与触摸事件在与动画不同的线程上处理的可能性。

我也在调试模式下运行并注意到动画实际上并未“提交”,直到控件离开methodCalledFromViewControllerTouchesEnded并返回touchesEnded:,从而使isMoving = NO;标志无效。

非常感谢任何防止重复动画的帮助。

3 个答案:

答案 0 :(得分:6)

如果你使用UIView的类方法

+ (void)animateWithDuration:(NSTimeInterval)duration 
                 animations:(void (^)(void))animations

默认情况下禁用用户交互,直到动画结束。它会为你节省很多工作。对于您,您需要使用完整方法,以便可以使用EaseIn选项。它看起来像这样

- (void) methodCalledFromViewControllerTouchesEnded {

        [UIView animateWithDuration:0.25f 
                              delay:0.0 
                            options:UIViewAnimationOptionCurveEaseIn 
                         animations:^(void){
                                     // You animations here
                         } 
                         completion: nil];

}

如果按照目前的方式进行,则需要更改一些内容。请记住,动画没有阻塞,因此当你在最后将isMoving设置为NO时,动画开始后立即发生,而不是在结束后发生。现在,让我重申上面的代码比你的方法简单得多,但是如果你想继续沿着你的路径继续下去,你需要为你的动画设置animationStopped完成方法,在那个方法中,将isMoving设置为NO。它看起来像这样:

isMoving = YES;
[UIView beginAnimations:@"move" context:NULL];
//...
[UIView setAnimationDidStopSelection:@selector(animationDidStop:finished:context:)];
// ... DO MOVE STUFF
//....
[UIView commitAnimations];

然后你会像这样实现选择器:

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
     isMoving = NO;
}

答案 1 :(得分:5)

我遇到了类似的问题,用以下方法解决了这个问题:

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];

答案 2 :(得分:1)

你的东西是正确的,除非你误解了动画的运作方式。它正如你告诉它的那样工作:P。

问题是您将isMoving设置为NO过早。动画块不会暂停代码的执行。相反,它会对动画进行排队并继续执行。

- (void) methodCalledFromViewControllerTouchesEnded {
    if (isMoving == YES) {
        NSLog (@"Don't start another animation!");
        return;
    }   
    isMoving = YES;

    [UIView animateWithDuration:.25 
                         animations:^(void){
                                     //DO STUFF HERE
                         } 
                         completion: ^(BOOL finished) {
                                     isMoving = NO;
                         }];
}

更多是你想要的。

如果你真的不想做块结构。然后去像

这样的东西
- (void) methodCalledFromViewControllerTouchesEnded {
    if (isMoving == YES) {
        NSLog (@"Don't start another animation!");
        return;
    }   
    isMoving = YES;

    ......

    [UIView beginAnimations:@"move" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationDuration:0.25f];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animate:finished:context:)];
    ...
    // DO MOVE STUFF
    ...
    [UIView commitAnimations];

}

-(void)animate:(NSString *)str_animationID finished:(BOOL)b_isFinished context:(void *)v_context {

    if(str_animationID == @"move") {
        isMoving = NO;
    } 
}