Animate AVPlayerLayer videoGravity свойство - PullRequest
4 голосов
/ 19 января 2012

Я пытаюсь скопировать поведение Apple при воспроизведении видео, которое позволяет пользователю растягивать видеоизображение, чтобы заполнить границы.

@interface FHVideoPlayerView : UIView
@end
@interface FHVideoPlayerView

+ (Class)layerClass
{
    return [AVPlayerLayer class];
}

- (void)setAspectMode:(FHVideoPlayerAspectMode)aspectMode animated:(BOOL)animated
{
    FHVideoPlayerAspectMode current = [self aspectMode];
    FHVideoPlayerAspectMode final   = aspectMode;

    NSString *fromValue;
    NSString *toValue;

    AVPlayerLayer *layer = (AVPlayerLayer *)[self layer];

    switch (current) {
        case FHVideoPlayerAspectFill:
            fromValue = AVLayerVideoGravityResizeAspectFill;
            break;
        case FHVideoPlayerAspectFit:
            fromValue = AVLayerVideoGravityResizeAspect;
            break;
       default:
           break;
    }

    switch (final) {
        case FHVideoPlayerAspectFill:
            toValue = AVLayerVideoGravityResizeAspectFill;
            break;
        case FHVideoPlayerAspectFit:
            toValue = AVLayerVideoGravityResizeAspect;
            break;
        default:
            break;
    }

    if (toValue != fromValue) {
        if (animated == YES) {
            // Manually added CABasicAnimation based on the understanding the implicit animations are disabled for CALayers that back a UIView
            CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"videoGravity"];
            [layer addAnimation:animation forKey:@"animateVideoGravity"];

            [CATransaction begin];
            [CATransaction setAnimationDuration:0.333];
        }

        [layer setVideoGravity:toValue];

        if (animated == YES) {
            [CATransaction commit];
        }
    }
}

Это прекрасно работает, когда я пытаюсь анимировать числовое свойство, такое каккак непрозрачность.Но, как вы заметили из ссылки на класс, свойство videoGravity AVPlayerLayer является строкой NSString.Ссылка на класс указывает на то, что она анимируема.

Так что мой вопрос: как!?

Я полагаю, что это, возможно, как-то связано со свойством содержимого CALayer и, возможно, contentsGravity.

Ответы [ 2 ]

5 голосов
/ 08 мая 2012

Как указал voromax, это ошибка в iOS 5.0.Я пересмотрел -[AVPlayerLayer setVideoGravity:] реализацию в iOS 5.1, чтобы понять, как должна работать анимация.Вот как обойти ошибку и получить хорошую анимацию на iOS 5.0.

@implementation VideoPlayerView

+ (Class) layerClass
{
    return [AVPlayerLayer class];
}

- (AVPlayerLayer *) playerLayer
{
    return (AVPlayerLayer *)[self layer];
}

- (NSString *) videoGravity
{
    return self.playerLayer.videoGravity;
}

- (void) setVideoGravity:(NSString *)videoGravity
{
    self.playerLayer.videoGravity = videoGravity;

    // Workaround a bug in iOS 5.0
    float avFoundationVersion = [[[NSBundle bundleForClass:[AVPlayerLayer class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] floatValue];
    if (avFoundationVersion < 292.24f)
    {
        @try
        {
            NSString *contentLayerKeyPath = [NSString stringWithFormat:@"%1$@%2$@.%3$@%2$@", @"player", [@"layer" capitalizedString], @"content"]; // playerLayer.contentLayer
            CALayer *contentLayer = [self.playerLayer valueForKeyPath:contentLayerKeyPath];
            if ([contentLayer isKindOfClass:[CALayer class]])
                [contentLayer addAnimation:[CABasicAnimation animation] forKey:@"sublayerTransform"];
        }
        @catch (NSException *exception)
        {
        }
        self.bounds = self.bounds;
    }
}

@end
1 голос
/ 08 марта 2012

Это была ошибка в iOS 5.0 и iOS 5.0.1.

После обновления до iOS 5.1 анимация изменения гравитации видео снова заработала.

...