UIView动画自动翻转时闪烁问题

7
我试图为一个空表单字段制作动画指示器,所以我使用下面的方法来动画到一个位置、反转动画并重复。在模拟器上这个方法可以正常工作,在我的3GS上看起来当完成块被调用时会出现闪烁。指示器会短暂地显示在中间位置,而不是回到原点。您有什么想法为什么会发生这种情况吗?谢谢。
- (void)bounceFormIndicator {
    if (formIndicator.superview == nil) {
        return;
    }

    int bounceDistance = 24;

    [UIView animateWithDuration:0.6 
                          delay:0 
                        options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction
                     animations:^{
                        CGRect indicatorFrame = formIndicator.frame;
                        indicatorFrame.origin.x += bounceDistance;
                        formIndicator.frame = indicatorFrame;
                     }completion:^(BOOL finished){
                        CGRect indicatorFrame = formIndicator.frame;
                        indicatorFrame.origin.x -= bounceDistance;
                        formIndicator.frame = indicatorFrame;
                        [self bounceFormIndicator];
                     }];
}

仍未解决,但我找到了一个解决方法。我使用UIViewAnimationOptionRepeat选项并完全删除完成块。 - brianpartridge
1个回答

13

我也遇到了同样的问题,于是求助于苹果的DTS(开发技术支持)来找一个解决方法。

根据DTS的说法,这种“闪烁”效果或回弹效果是预期行为……我很长时间以来一直认为是我的项目出了什么问题。

特别是因为文档中说明:

UIViewAnimationOptionAutoreverse:使动画向前和向后运行。

必须与UIViewAnimationOptionRepeat选项组合使用。

为了消除闪烁,我需要做两件事情。

由于我的实现方式是动态的,所以你可能不需要实现第一步,但我将保留这个步骤供参考。

首先,我检查要传递给动画的选项中是否包含UIViewAnimationOptionAutoreverse,并且没有UIViewAnimationOptionRepeat……如果有,我会添加一行代码从选项中删除它:

animationOptions &= ~UIViewAnimationOptionAutoreverse;

为了创建不重复的反转动画,我将一个相反的UIView动画添加为完成块。如果它是UIViewAnimationOptionCurveEaseInUIViewAnimationOptionCurveEaseOut,我还反转了缓动效果...

我的项目代码如下:

从对象的animationOptions中剥离自动反转选项的语句:

if ((animationOptions & AUTOREVERSE) == AUTOREVERSE) {
    self.shouldAutoreverse = YES;
    animationOptions &= ~AUTOREVERSE;
}

一个处理动画的重写属性设置器示例:

-(void)setCenter:(CGPoint)center {
    CGPoint oldCenter = CGPointMake(self.center.x, self.center.y);

    void (^animationBlock) (void) = ^ { super.center = center; };
    void (^completionBlock) (BOOL) = nil;

    BOOL animationShouldNotRepeat = (self.animationOptions & REPEAT) !=  REPEAT;
    if(self.shouldAutoreverse && animationShouldNotRepeat) {
        completionBlock = ^ (BOOL animationIsComplete) {
            [self autoreverseAnimation:^ { super.center = oldCenter;}];
        };
    }
    [self animateWithBlock:animationBlock completion:completionBlock];
}

在不重复的情况下进行反转操作时所调用的完成方法:

-(void)autoreverseAnimation:(void (^)(void))animationBlock {
        C4AnimationOptions autoreverseOptions = BEGINCURRENT;
        if((self.animationOptions & LINEAR) == LINEAR) autoreverseOptions |= LINEAR;
        else if((self.animationOptions & EASEIN) == EASEIN) autoreverseOptions |= EASEOUT;
        else if((self.animationOptions & EASEOUT) == EASEOUT) autoreverseOptions |= EASEIN;

        [UIView animateWithDuration:self.animationDuration
                              delay:0
                            options:autoreverseOptions
                         animations:animationBlock
                         completion:nil];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接