Animate AVPlayerLayer videoGravity property

匿名 (未验证) 提交于 2019-12-03 02:16:02

问题:

I'm trying to copy Apple's behavior in video playback that allows the user to stretch the video image to fill the bounds.

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

This works just fine when I try and animate a numeric property such as opacity. But, you'll notice from the class reference, AVPlayerLayer's videoGravity property is an NSString. The class reference does points out that it is animatable.

So my question is: How!?

I believe this is probably related somehow to CALayer's content property and possibly contentsGravity.

回答1:

As voromax pointed out, this is a bug in iOS 5.0. I reverse engineered -[AVPlayerLayer setVideoGravity:] implementation in iOS 5.1 in order to understand how the animation was supposed to work. Here is how to workaround the bug and have a nice animation on 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 


回答2:

It was a bug in iOS 5.0 and iOS 5.0.1.

After updating to iOS 5.1 the video gravity changing animation begun to work again.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!