5

I am using a UIViewPropertyAnimator to animate the frame of a UICollectionViewCell. I look at the velocity of a pan gesture recognizer to decide whether the animator should finish naturally or reverse and go back to the initial state.

In all simulators, on my iPhone 5s as well as 6s+, these animations run flawlessly. On my iPhone 7+, however, I am getting strange frame flickering whenever I reverse the animation. See code below for how I do this. The effect on the iPhone 7+ is that as soon as I set reversed = YES and then call continueAnimationWithTimingParameters:durationFactor:, the frame immediately jumps to a completely different part of the screen, and then runs the reversed animation from there. Only after the animation has finished running does the frame jump back to where it was supposed to revert back to.

I have tried to remove the use of spring timing parameters, but that did not make a difference.

This is an abstracted version of the code:

- (void)prepareAnimation {
    // Called when user begins panning in certain direction
    // ...
    self.cardFrameAnimator = [[UIViewPropertyAnimator alloc] initWithDuration:0.5 dampingRatio:0.8 animations:^{
        [self currentCell].frame = targetFrame;
    }];
}

- (void)panningEndedWithTranslation:(CGPoint)translation velocity:(CGPoint)velocity
{
    if (self.cardFrameAnimator.isRunning)
    {
        return;
    }

    CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
    CGVector velocityVector = CGVectorMake(velocity.x / 500, velocity.y / 500);

    __weak CardStackCollectionViewController *weakSelf = self;

    switch (self.currentState) {
        case CurrentStateStacked:
            if (translation.y <= -screenHeight / 3 || velocity.y <= -100)
            {
                // Let the animation run to completion
                self.cardFrameAnimator.reversed = NO;
                [self setCurrentCellsCornerRadius:0];
                [self.cardFrameAnimator addCompletion:^(UIViewAnimatingPosition finalPosition) {
                    weakSelf.activeCellState = CurrentStateFullscreen;
                }];
            }
            else
            {
                // Revert the animation back to the default state
                self.cardFrameAnimator.reversed = YES;
                [self setCurrentCellsCornerRadius:20];
                [self.cardFrameAnimator addCompletion:^(UIViewAnimatingPosition finalPosition) {
                    weakSelf.activeCellState = CurrentStateStacked;
                }];
            }
            break;
        case CurrentStateFullscreen:
            if (translation.y >= screenHeight / 3 || velocity.y >= 100)
            {
                // Let the animation run to completion
                self.cardFrameAnimator.reversed = NO;
                [self setCurrentCellsCornerRadius:20];
                [self.cardFrameAnimator addCompletion:^(UIViewAnimatingPosition finalPosition) {
                    weakSelf.activeCellState = CurrentStateStacked;
                }];
            }
            else
            {
                // Revert the animation back to the default state
                self.cardFrameAnimator.reversed = YES;
                [self setCurrentCellsCornerRadius:0];
                [self.cardFrameAnimator addCompletion:^(UIViewAnimatingPosition finalPosition) {
                    weakSelf.activeCellState = CurrentCellStateFullscreen;
                }];
            }
            break;
    }

    UISpringTimingParameters *springParameters = [[UISpringTimingParameters alloc] initWithDampingRatio:0.8 initialVelocity:velocityVector];
    [self.cardFrameAnimator continueAnimationWithTimingParameters:springParameters durationFactor:1.0];
}
Daniel Larsson
  • 5,762
  • 5
  • 39
  • 75
  • Didi you solve this? I noticed the same difference between ios10 and ios11 on all devices. It seems to be related on how the `UIViewPropertyAnimator` manages `fractionComplete` property when `reversed` value changed. On iOS10, when changed, for some moments `fractionComplete` continue to be calculated as before and only after some fractions of time jumps to his complementary. On iOS11 this happens instantly. – Giovanni Trezzi Sep 24 '17 at 16:45
  • Still looking for a solution, I described my similar problem here: [link](https://stackoverflow.com/questions/46406670/uiviewpropertyanimator-different-behaviour-on-ios10-and-ios11-reversing-an-anima) – Giovanni Trezzi Sep 26 '17 at 10:02
  • I have the same issue – Ruben Nahatakyan Jul 19 '20 at 19:33

0 Answers0