2012-01-18 189 views
4

我試圖複製Apple在視頻播放中的行爲,允許用戶伸展視頻圖像來填充邊界。Animate AVPlayerLayer videoGravity屬性

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

當我嘗試和動畫數值屬性,如不透明度這工作就好了。但是,您會從類參考中注意到,AVPlayerLayer的videoGravity屬性是一個NSString。類參考確實指出它是可以動畫的。

所以我的問題是:如何!?

我相信這可能與CALayer的內容屬性和可能的​​contentGravity有關。

回答

5

voromax指出,這是iOS 5.0中的一個錯誤。爲了理解動畫應該如何工作,我在iOS 5.1中逆向工程-[AVPlayerLayer setVideoGravity:]實現。以下是如何解決該錯誤並在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:@"%[email protected]%[email protected]%[email protected]%[email protected]", @"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 
+0

所以我只是好奇,你有什麼與這些格式說明符?我知道你試圖混淆字符串,但你能解釋說明符嗎? – 2012-05-08 05:37:26

+0

真棒解決方法!這在5.0發佈時給我帶來了很多麻煩,它最終在5.1中得到修復,但補充說修復是一個好主意。 – steipete 2012-05-08 08:24:12

+0

哈哈'AVPlayerLayer'。我喜歡這個名字。 :) – 2012-05-08 08:26:05

1

這是iOS 5.0和iOS 5.0.1中的一個錯誤。

更新到iOS 5.1後,視頻重力變化動畫重新開始工作。

+1

嗯......看起來你是對的。雖然Apple的視頻播放視圖控制器不受此影響。所以也許有另一種方式來動畫視頻引力? – edelaney05 2012-03-09 20:56:17

+0

我想他們只是沒有重新編譯他們的MPMoviePlayer,因爲iOS 4.3 – voromax 2012-03-10 08:26:52

+0

我不這麼認爲 - 他們添加了一個新屬性(airPlayVideoActive)和一個新的通知。 [API差異4.3至5.0](https://developer.apple.com/library/ios/#releasenotes/General/iOS50APIDiff/index.html) – edelaney05 2012-03-11 21:01:05