Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView animation flickering with autoreverse

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];
                     }];
}
like image 656
brianpartridge Avatar asked Sep 18 '11 16:09

brianpartridge


1 Answers

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];
}
like image 102
C4 - Travis Avatar answered Oct 06 '22 11:10

C4 - Travis