2016-02-16 21 views
7

Próbuję dodać AVPlayerLayer do UIViewAVPlayerLayer nie granice do UIView ramie

self.player = AVPlayer(URL: NSURL(fileURLWithPath: path!)) 
    self.playerLayer = AVPlayerLayer(player: player); 
    self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
    self.playerLayer.frame = ctrVideo.bounds; 
    self.ctrVideo.layer.addSublayer(playerLayer); 
    player.play(); 

Jest to pojemnik filmu wideo (na niebiesko):

This is the view:

Ograniczenia: Constraints:

Wynik końcowy: enter image description here

Nie mogę zrozumieć, dlaczego wideo nie jest powiązane z współrzędnymi UIVIew. Jeśli ograniczę go do superview kontrolera, jest w porządku.

+0

podwarstwa nie zmieni rozmiar automatycznie po zmienia się ramka widoku, musisz to zrobić ręcznie. – almas

+0

Ale dlaczego to działa po dodaniu do widoku root? –

+1

Prawdopodobnie dlatego, że widok główny został już poprawnie zmieniony w tym czasie. Spróbuj wydrukować rootview.frame i ctrVideo.frame po dodaniu podwarstwy, zobacz, czy są jakieś różnice. – almas

Odpowiedz

13

Sublayer nie zmieni rozmiaru automatycznie po zmianie widoku ramki, należy to zrobić ręcznie. Możesz podklasować UIView, aby było łatwiej.

class VideoContainerView: UIView { 
    var playerLayer: CALayer? 
    override func layoutSublayersOfLayer(layer: CALayer) { 
    super.layoutSublayersOfLayer(layer) 
    playerLayer?.frame = self.bounds 
    } 
} 

A potem w kodzie:

self.player = AVPlayer(URL: NSURL(fileURLWithPath: path!)) 
self.playerLayer = AVPlayerLayer(player: player); 
self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
self.playerLayer.frame = ctrVideo.bounds; 
self.ctrVideo.layer.addSublayer(playerLayer); 
self.ctrVideo.playerLayer = playerLayer; 
player.play(); 

Wystarczy upewnić się, że zmiany tej klasy swojego "ctrVideo" z UIView do VideoContainerView.

+0

omg, który działał –

+0

dziękuję, sir, to jest idealne – Andres

+1

update for swift 3: 'func layoutSublayersOfLayer (layer: CALayer)' został zmieniony na 'func layoutSublayers (of layer: CALayer) {}' – Asususer

-1

Dodaję AVPlayerLayer w zdarzeniu viewDidLoad ... Przed nałożeniem ograniczeń.

-1

Oto widok z tyłu, który próbuje zachować proporcje.

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 
0

Oto niesamowite odpowiedź @almas' w Swift 4

class VideoContainerView: UIView {  
    var playerLayer: CALayer? 

    override func layoutSublayers(of layer: CALayer) { 
     super.layoutSublayers(of: layer) 
     playerLayer?.frame = self.bounds 
    } 
}