UIView 动画随着自动反转而闪烁

发布于 2024-12-05 08:16:39 字数 1082 浏览 1 评论 0原文

我正在尝试将指示器设置为空表单字段的动画,因此我使用下面的方法将动画设置为某个位置,反转动画,然后重复。在模拟器中,这工作正常,在我的 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];
                     }];
}

I'm trying to animate an indicator to an empty form field so I'm using the method below to animate to a position, reverse the animation, and repeat. In the simulator this works fine, on my 3GS it looks like there is a flicker right when the completion block is called. The indicator is briefly shown at the middle position rather than back at it's origin.

Any thoughts on why this is happening? Thanks.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

各自安好 2024-12-12 08:16:39

我遇到了同样的问题,并前往 Apple 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];
}

I had the same problem, and went to Apple DTS to help with a workaround.

As per DTS, this 'flickering' effect, or snap-back effect is the expected behaviour... I thought that I was doing something wrong with my project for a long time.

In particular it is this way because the documentation states, for

UIViewAnimationOptionAutoreverse Run the animation backwards and
forwards.

Must be combined with the UIViewAnimationOptionRepeat option.

In order to get the flicker to go away, I had to do 2 things.

My implementation was dynamic, so you might not have to implement the first step, but I'll keep it in here just for reference.

First, I checked to see if UIViewAnimationOptionAutoreverse was part of the options I was going to pass into my animation, and UIViewAnimationOptionRepeat was not... If so, I stripped it from the options by adding a line like:

animationOptions &= ~UIViewAnimationOptionAutoreverse;

To create the reversing animation without repeating, I added an opposite UIView animation as my completion block. I also inverted the easing if it was either UIViewAnimationOptionCurveEaseIn or UIViewAnimationOptionCurveEaseOut...

The code from my project follows:

The statement that strips the autoreverse option from an object's animationOptions:

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

An example of an overridden property setter that handles an animation:

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

The completion method called for in the case of reversing without repeating:

-(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];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文