0

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

- (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;
}

然后我设置isMovingNO这样后续调用touchesEnded:不会在当前动画正在进行时启动另一个动画。但是,如果用户在初始动画正在进行时继续触摸,则此FAILS和动画会重复执行。

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

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

任何有助于防止重复动画的帮助将不胜感激。

4

3 回答 3

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;
}
于 2011-04-21T18:43:25.707 回答
5

我有一个类似的问题,解决了它:

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
于 2012-12-17T15:57:10.407 回答
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;
    } 
}
于 2011-04-21T18:53:10.820 回答