2012-02-29 2 views
13

MonoTouch의 AV Foundation에서 제공하는 AVPlayer API를 사용하여 비디오 플레이어를 개발 중입니다. 전체 화면 모드를 구현하려고합니다. 전체 화면 : 부모보기의 크기를 조정할 때 AVPlayerLayer의 크기가 조절되지 않습니다.

내가 가진, 비디오 프레임을 표시하려면 내가 재생보기 층의 서브 뷰으로 AVPlayerLayer을 추가 UIView의 (의 재생보기를 부르 자) :

UIView *playbackView = ... 
AVPlayerLayer *playerLayer = ... 
[playbackView.layer addSublayer:playerLayer]; 

레이어 속성 그런 설정됩니다

playerLayer.needsDisplayOnBoundsChange = YES; 
playbackView.layer.needsDisplayOnBoundsChange = YES; 

재생보기 크기가 변경되면 크기가 조정되는지 확인하십시오. 처음에는 재생 뷰의 좌표 (0, 0, 320, 180)가 UI의 맨 위에 표시됩니다. 그럼, 창 크기로서 재생보기 프레임 크기를 설정하여 전체 화면 애니메이션을하고있는 중이 야 : 그것은

playbackView.frame = playbackView.window.bounds; 

가 잘 작동합니다. 재생 뷰는 이제 모든 창을 채 웁니다 (보려는 배경색 설정). 하지만 내 AVPlayerLayer는 이전처럼 전체 화면 모드가 아닌보기의 맨 위에 머물러 있습니다.

재생보기의 새 크기에 따라 AVPlayer 레이어의 크기가 조정되지 않는 이유는 무엇입니까? AVPlayerLayer에서도 애니메이션을 만들어야합니까? setNeedsLayout, layoutSubviews를 새로 고침 (변경되지 않은 것 같은데 ...)? AVPlayerLayer를 제거하고 다시 추가 하시겠습니까?

+0

한가지 해결책도에 따른 계층 프레임 크기를 조절하는 것이다 애니메이션 도중 재생 뷰 프레임 (playerLayer.frame = playbackView.frame). 하지만 이렇게하면 레이어가 애니메이션으로 표시되지 않고 최종 크기로 직접 표시됩니다. 이 변경 사항을 어떻게 애니메이트 할 수 있습니까? UIView 애니메이션 대신 Core Animation을 사용 하시겠습니까? – nicolas

답변

25

하위 계층으로 추가하지 마십시오. 그냥 다음과 같이 AVPlayerLayer로 playbackView의 레이어를 사용 :

+ (Class)layerClass { 
    return [AVPlayerLayer class]; 
} 
- (AVPlayer*)player { 
    return [(AVPlayerLayer *)[self layer] player]; 
} 
- (void)setPlayer:(AVPlayer *)player { 
    [(AVPlayerLayer *)[self layer] setPlayer:player]; 
} 

AV Foundation Programming Guide - 더 플레이어보기

+0

하위 레이어로 추가해야하는 경우 어떻게해야합니까? 예를 들어 AVPlayerLayer를 비롯한 여러 하위 레이어가 포함 된 레이어 호스팅보기를 사용합니다. – Dalmazio

+3

Apple은 자신의 AVPlayer 예제를 swift를 사용하여 구현하는 방법을 보여주는 버전으로 업데이트했습니다. https://developer.apple.com/library/prerelease/ios/samplecode/AVFoundationSimplePlayer-iOS/Listings/Swift_AVFoundationSimplePlayer_iOS_PlayerView_swift.html#//apple_ref/ doc/uid/TP40016103-Swift_AVFoundationSimplePlayer_iOS_PlayerView_swift-DontLinkElementID_14 – morgman

+0

NSView에서 어떻게하면 좋을까요?NSView에는'layerClass'가 없습니다. – iluvcapra

6

을 경우 당신이 하위 계층으로 AVPlayerLayer을 추가, 당신은

- (void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 

    self.avPlayerLayer.frame = self.movieContainerView.bounds; 
} 
+0

나쁜 아이디어를 참조하십시오. 플레이어이기 때문에, 표시기 시간이 업데이트 될 때마다 – jose920405

+0

파견 된이 기능은 나에게 싫증이났다. 이 일을하지 말아라. – mahieddine

+1

나에게 매우 도움이되는 좋은 대답. – Genevios

0

가 자사의 프레임 업데이트해야 이것을 달성하는 더 좋은 방법. 여기에 AVPlayerLayer -backed view가 있는데, 이는 비디오 종횡비를 유지하려고합니다. 일반적으로 AutoLayout을 사용하십시오.

PlayerView.h :

@interface PlayerView : UIView 

@property (strong, nonatomic) AVPlayerLayer *layer; 

@end 

PlayerView.m :

@interface PlayerView() 

@property (strong, nonatomic) NSLayoutConstraint *aspectConstraint; 

@end 

@implementation PlayerView 

@dynamic layer; 

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

- (instancetype)init { 
    self = [super init]; 
    if (self) { 
     self.userInteractionEnabled = NO; 

     [self addObserver:self forKeyPath:@"layer.videoRect" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew context:nil]; 
    } 
    return self; 
} 

- (void)dealloc { 
    [self removeObserver:self forKeyPath:@"layer.videoRect"]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { 
    if ([keyPath isEqualToString:@"layer.videoRect"]) { 
     CGSize size = [change[NSKeyValueChangeNewKey] CGRectValue].size; 
     if (change[NSKeyValueChangeNewKey] && size.width && size.height) { 
      self.aspectConstraint.active = NO; 
      self.aspectConstraint = [self.widthAnchor constraintEqualToAnchor:self.heightAnchor multiplier:size.width/size.height]; 
      self.aspectConstraint.priority = UILayoutPriorityDefaultHigh; 
      self.aspectConstraint.active = YES; 
     } 
     else { 
      self.aspectConstraint.active = NO; 
     } 
    } 
} 

@end 

그리고 Swift에서 동일한 용액 :

import UIKit 
import AVFoundation 

class PlayerView : UIView { 

    override var layer: AVPlayerLayer { 
     return super.layer as! AVPlayerLayer 
    } 

    override class var layerClass: AnyClass { 
     return AVPlayerLayer.self 
    } 

    var aspectConstraint: NSLayoutConstraint? 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     self.isUserInteractionEnabled = false 
     self.addObserver(self, forKeyPath:"layer.videoRect", options:[.initial, .new], context:nil) 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     self.isUserInteractionEnabled = false 
     self.addObserver(self, forKeyPath:"layer.videoRect", options:[.initial, .new], context:nil) 
    } 

    deinit { 
     self.removeObserver(self, forKeyPath: "layer.videoRect") 
    } 

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
     if (keyPath == "layer.videoRect") { 
      if let rect = change?[.newKey] as? NSValue { 
       let size = rect.cgRectValue.size 
       if (size.width > 0 && size.height > 0) { 
        self.aspectConstraint?.isActive = false 
        self.aspectConstraint = self.widthAnchor.constraint(equalTo: self.heightAnchor, multiplier:size.width/size.height) 
        self.aspectConstraint?.priority = UILayoutPriorityDefaultHigh 
        self.aspectConstraint?.isActive = true 
       } 
       else { 
        self.aspectConstraint?.isActive = false 
       } 
      } 
     } 
    } 
} 
관련 문제