2012-04-12 101 views
40

我有一个UIView,其中包含一个AVPlayer来显示视频。改变方向时,我需要更改视频的大小和位置。当UIView帧发生变化时,视图内的AVPlayer层不会调整大小

我对调整图层大小不是很有经验,所以我在调整视频时遇到问题。

我通过创建AVPlayer并把它的玩家我videoHolderView的层开始:

NSURL *videoURL = [NSURL fileURLWithPath:videoPath]; 
self.avPlayer = [AVPlayer playerWithURL:videoURL]; 

AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; 
playerLayer.frame = videoHolderView.bounds; 
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; 
playerLayer.needsDisplayOnBoundsChange = YES; 

[videoHolderView.layer addSublayer:playerLayer]; 
videoHolderView.layer.needsDisplayOnBoundsChange = YES; 

然后,在以后,我改变videoHolderView的帧的大小和位置:

[videoHolderView setFrame:CGRectMake(0, 0, 768, 502)]; 

在这一点上,我需要AVPlayer调整到这些相同的尺寸。这不会自动发生 - avPlayer在videoHolderView中保持小尺寸。

如果有人可以帮忙,我会非常感谢任何建议。

谢谢你们。

回答

13

最后,我通过将AVPlayerLayer重新添加到UIView中解决了这个问题。我不知道为什么改变框架删除了图层,但它确实如此。这是最终的解决方案:

//amend the frame of the view 
[videoHolderView setFrame:CGRectMake(0, 0, 768, 502)]; 

//reset the layer's frame, and re-add it to the view 
AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; 
playerLayer.frame = videoHolderView.bounds; 
[videoHolderView.layer addSublayer:playerLayer]; 
+0

我不确定是否需要删除并重新添加它,但是我通过将该图层的框架设置为过去的持有者视图边界来完成此操作。 – 2015-04-13 22:50:10

+0

我将这种方式应用于我的项目,效果很好。与AVPlayerViewController和AVPlayerController相比,当您的项目仍然使用自动调整时,它具有更好的性能,并且没有自动布局警告问题。 – Jacky 2016-10-24 05:38:12

+0

谢谢它的作品。 – 2017-04-25 15:14:08

1

第一步:检查出的UIView的自动尺寸财产UIVIew.h

@属性(非原子)UIViewAutoresizing autoresizingMask; //简单的调整大小。默认为UIViewAutoresizingNone

此属性记录IB中的“弹簧和支柱”控件,但它会带您进行一些实验以获得您想要的结果。

+0

Jay!谢谢!我试图将其改变为各种各样的东西,但无论我设置了什么,它都不会对视频产生影响。在更改视图大小以强制调整大小后,是否需要调用另一个函数? – theDuncs 2012-04-12 15:41:31

+0

你在哪里调用[videoHolderView setNeedsLayout]? – 2012-04-12 15:53:52

+0

我不是在任何地方叫它,不。我只是在更改视图框架后尝试调用它,仍然没有任何区别。 – theDuncs 2012-04-12 15:56:43

2

该Dunc的答案不适合我。我发现了一个解决方案,更简单:我只是需要在UIView的改变之后调整AVPlayerLayer的框架:

avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); 

this blog时所说的那样,一个视图的框架也影响了层在它。

当您更改视图的框架时,它只是更改图层的框架。

对于这种情况,这是不正确的。

+0

这是我的解决方案。现在,我在更改superLayer后设置了AVPlayerLayer。调整大小现在是好的。谢谢。 +1 – 2015-03-17 13:27:42

18

实际上,您不应该将AVPlayer的图层添加为子图层。而不是你应该使用下面的方法,在你想要显示AVPlayer的视图的子类中。

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

并使用以下行添加(设置)播放器图层。

[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer]; 

希望它可以帮助;-)

+0

聪明!谢谢Suran。 – KPM 2015-04-16 13:01:51

+0

这工作得很好!谢谢! – 2017-01-09 21:07:55

53
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit; 
+0

这导致剪切视频 – jose920405 2015-07-02 13:21:44

+4

这不解决这个问题,裁剪视频 – 2015-11-02 19:42:23

+2

可以使用AspectFit然后代替AspectFill – NSGangster 2015-11-23 18:33:47

4

您可以通过重写-layoutSubviews方法改变层的框架:

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 
    self.playerLayer.frame = self.bounds; 
} 
1

要到playerLayer,您可以通过videoHolderView.layer.sublayers需要循环并改变每一个。

这是我做的雨燕在2.2

if let sublayers = videoHolderView.layer.sublayers{ 
    for layer in sublayers where layer is AVPlayerLayer{ 
     layer.frame.size = ... // change size of the layer here 
    } 
} 
0

任何一个搜索Xamarin版本,因为我正在寻找

不添加AVPlayerLayer如子,但设置层Avplayer层

[Export("layerClass")] 
public static Class LayerClass() 
{ 
    return new Class(typeof(AVPlayerLayer)); 
} 

下面的行设置的层

(this.Layer as AVPlayerLayer).Player = _player; // Acplayer 
0

我的雨燕2.3有这个问题,我解决了写一个适当的PlayerView类并将其设置为子视图:

import UIKit 
import AVKit 
import AVFoundation 

class PlayerPreviewView: UIView { 

    override class func layerClass() -> AnyClass { 
     return AVPlayerLayer.self 
    } 

    var player: AVPlayer? { 
     get { 
      return playerLayer.player 
     } 

     set { 
      playerLayer.player = newValue 
     } 
    } 

    var playerLayer: AVPlayerLayer { 
     return layer as! AVPlayerLayer 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     playerLayer.videoGravity = AVLayerVideoGravityResize 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     playerLayer.videoGravity = AVLayerVideoGravityResize 
    } 

} 

在呈现的ViewController:

private func play(asset asset: AVURLAsset){ 
    let playerItem = AVPlayerItem(asset: asset) 

    player = AVPlayer(playerItem: playerItem) 
    player?.actionAtItemEnd = .None 
    player?.muted = true 

    playerPreviewView = PlayerPreviewView(frame: CGRectZero) 
    view.addSubview(playerPreviewView) 
    playerPreviewView.player = player 


    playerPreviewView.translatesAutoresizingMaskIntoConstraints = false 
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": playerPreviewView])) 
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": playerPreviewView])) 


    player?.play() 

    NSNotificationCenter.defaultCenter().addObserver(self, 
                selector: #selector(SplashScreenViewController.videoDidFinish), 
                name: AVPlayerItemDidPlayToEndTimeNotification, 
                object: nil) 
} 
10

转换@苏冉的解决方案,以斯威夫特3:

首先,创建一个继承UIView的类,其中只覆盖1个变量:

import UIKit 
import AVFoundation 

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

然后使用界面生成器添加一个简单的UIView,并改变其类刚创建的一个:AVPlayerView

change class of regular UIView to AVPlayerView

然后,使该视图的出口。说它avPlayerView

@IBOutlet weak var avPlayerView: AVPlayerView! 

现在,您可以使用您的看法里面的ViewController和访问其avlayer这样的:现在

let avPlayer = AVPlayer(url: video) 
let castedLayer = avPlayerView.layer as! AVPlayerLayer 
castedLayer.player = avPlayer 
avPlayer.play() 

层将遵循制约就像一个普通的层会做。无需手动更改边界或大小。

+0

干净的解决方案!作品 – 2017-02-09 20:03:37

+0

AVPlayerView仅适用于OSX。问题是关于iOS。 – 2017-04-19 13:28:29

+0

AVPlayerView是我自己定制的类;-)我不知道它是在OS X中使用的。 – Sam 2017-04-20 16:12:46

1

实测值由Marco Santarossa一个伟大的文章显示多种方法来固定。 https://marcosantadev.com/calayer-auto-layout-swift/

我用他的第一个建议在viewDidLayoutSubViews()事件中重置了层框架。

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    playerLayer.frame = view.layer.bounds 
} 
相关问题