我有一个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内的小尺寸。
如果有人可以帮助,我会很感激的任何建议。
多谢你们。
Answer 1:
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
Answer 2:
转换@苏冉的解决方案,斯威夫特3:
首先,创建一个类继承UIView的,你只重写1变量:
import UIKit
import AVFoundation
class AVPlayerView: UIView {
override class var layerClass: AnyClass {
return AVPlayerLayer.self
}
}
然后,使用界面生成器添加一个简单的UIView,并改变其类刚创建的一个: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()
该层现在将遵循制约就像一个普通的层会做。 无需手动更改范围或大小。
Answer 3:
其实你不应该添加AVPlayer的层作为子层。 相反的,你应该使用下面的方法,在其中要显示AVPlayer视图的子类。
+ (Class)layerClass
{
return [AVPlayerLayer class];
}
并使用以下行添加(组)选手层。
[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];
希望能帮助到你;-)
Answer 4:
最后,我通过重新添加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];
Answer 5:
您可以通过重写改变层的框架-layoutSubviews
方法:
- (void)layoutSubviews
{
[super layoutSubviews];
self.playerLayer.frame = self.bounds;
}
Answer 6:
发现马可Santarossa一个伟大的文章,显示多种方法来固定。 https://marcosantadev.com/calayer-auto-layout-swift/
我用他的第一个建议复位viewDidLayoutSubViews()事件期间层帧。
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
playerLayer.frame = view.layer.bounds
}
Answer 7:
theDunc的回答并没有为我工作。 我发现了一个解决方案,更简单:我只是需要在不断变化的UIView之后调整AVPlayerLayer的框架:
avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
在这篇博客中所说的那样,一个视图的框架也影响到它的层。
当您更改视图的框架,它只是改变了层的框架。
对于这种情况,这是不正确的。
Answer 8:
第一步:检查出UIVIew.h的UIView的自动尺寸属性
@属性(非原子)UIViewAutoresizing autoresizingMask; //简单的调整大小。 默认值是UIViewAutoresizingNone
此属性记者的“弹簧和支柱”,在IB控制,但它会带你进行一些试验,以得到你想要的结果。
Answer 9:
要到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
}
}
Answer 10:
我在雨燕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)
}
Answer 11:
任何一个搜索Xamarin版本,因为我正在寻找
不添加AVPlayerLayer如子,但设置层Avplayer层
[Export("layerClass")]
public static Class LayerClass()
{
return new Class(typeof(AVPlayerLayer));
}
下面的行设置的层
(this.Layer as AVPlayerLayer).Player = _player; // Acplayer
Answer 12:
对于那些你谁是只关注设备旋转过程中调整的AVPlayer,你可以改变在viewWillTransition您层帧(尺寸:CGSize,有协调:UIViewControllerTransitionCoordinator)方法,如下图所示。
//Swift 4
//Method in UIViewController
//Variable definitions are:
//self.layer is the AVPlayerLayer
//self.videoPlayerView is the view that the AVPlayerLayer is the sublayer of
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { context in
self.layer.layoutIfNeeded()
UIView.animate(
withDuration: context.transitionDuration,
animations: {
self.layer.frame = self.videoPlayerView.bounds
}
)
}, completion: nil)
}
这将在旋转过程中的所有其他视图沿动画的层框架。
文章来源: AVPlayer layer inside a view does not resize when UIView frame changes