Плавно поверните изображение кнопки обновления, чтобы оно завершилось до ближайшего поворота iOS

Я пытаюсь анимировать кнопку обновления, чтобы она вращалась, указывая на то, что обновление выполняется. Он должен быть плавным, чтобы, если обновление занимает всего 0,1 секунды, мы все равно делали полный оборот, чтобы пользователь мог подтвердить, что что-то произошло, и что это плавный переход. Он также должен продолжать вращаться, пока я не остановлю его, однако остановка не должна резко останавливать его, а только сказать ему завершить текущий поворот.

Изначально я сделал что-то вроде этого

CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2.0 * 10];
rotationAnimation.cumulative = YES;
rotationAnimation.duration = 10;
[self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

И останавливаясь так

[self.layer removeAllAnimations];

Это работало нормально в том смысле, что анимация плавно продолжалась за пределами 2pi радиан, однако, когда обновление занимало менее 1/10 секунды, это не выглядело бы очень плавно, поскольку анимация проходила бы 10% пути, а затем внезапно останавливалась и метод removeAllAnimations сбрасывает изображение до значения по умолчанию.

Мне удалось обойти этот альтернативный метод остановки

    CALayer *presentLayer = self.layer.presentationLayer;
    float currentAngle = [(NSNumber *) [presentLayer valueForKeyPath:@"transform.rotation.z"] floatValue];

    [self.layer removeAllAnimations];   

    if (currentAngle < 0) {
        currentAngle = 2 * ABS(currentAngle);
    }

    float rotationProgressPercent = currentAngle / (2 * M_PI);    
    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.fromValue = [NSNumber numberWithFloat:currentAngle];
    rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2];
    rotationAnimation.cumulative = YES;
    rotationAnimation.duration = 1 - rotationProgressPercent;

В основном я получаю текущий угол поворота в радианах, останавливаю анимацию и начинаю новую анимацию с этой позиции до двух пи. Мне нужно немного поработать с продолжительностью, чтобы поддерживать постоянную скорость, аспект скорости работает нормально, но проблема в том, что анимация имеет очень небольшое отставание / подергивание. Я считаю, что это связано с тем, что анимация остановки асинхронно отправляет этот запрос в систему (это всего лишь предположение), и что мой текущий угол устарел к тому времени, когда я иду делать свою вторую анимацию.

Есть ли другие подходы, которые я могу попробовать.


person Luke De Feo    schedule 05.06.2014    source источник


Ответы (1)


Итак, я в конце концов нашел решение, как это полезно

-(void)startSpinning {
    if (animating) {
        return;
    }
    animating = YES;
    [self rotateViewWithDuration:1 byAngle:M_PI * 2];

}

- (void)stopSpinning {
    animating = NO;
}


- (void)rotateViewWithDuration:(CFTimeInterval)duration byAngle:(CGFloat)angle {


    [CATransaction begin];
    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.byValue = [NSNumber numberWithFloat:angle];
    rotationAnimation.duration = duration;
    rotationAnimation.removedOnCompletion = YES;

    [CATransaction setCompletionBlock:^{

        if (animating) {
            [self rotateViewWithDuration:duration byAngle:angle];
        }
    }];

    [self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
    [CATransaction commit];
}
person Luke De Feo    schedule 05.06.2014