视图内的AVPlayer图层在UIView帧更改时不resize
我有一个UIView
包含一个AVPlayer
来显示video。 改变方向时,我需要改变video的大小和位置。
我对调整层次不是很有经验,所以我在调整video时遇到了问题。
我开始创buildAVPlayer
并将其播放器添加到我的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内的小尺寸。
如果有人可以帮忙,我真的很感激任何意见。
多谢你们。
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
其实你不应该把AVPlayer的图层添加为子图层。 而不是你应该使用下面的方法,在你想要显示AVPlayer的视图的子类。
+ (Class)layerClass { return [AVPlayerLayer class]; }
并使用下面的行添加(设置)播放器层。
[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];
希望能帮助到你;-)
最后,我通过将AVPlayerLayer重新添加到UIView中解决了这个问题。 我不知道为什么改变框架删除图层,但它确实。 这是最终的解决scheme:
//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];
将@ Suran的解决scheme转换成Swift 3:
首先,创build一个inheritanceUIView的类,只覆盖1个variables:
import UIKit import AVFoundation class AVPlayerView: UIView { override class var layerClass: AnyClass { return AVPlayerLayer.self } }
然后使用界面生成器添加一个简单的UIView,并将其类更改为刚创build的类: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()
现在,图层将像普通图层一样遵循约束条件。 无需手动更改边界或大小。
您可以通过覆盖-layoutSubviews
方法来更改图层的框架:
- (void)layoutSubviews { [super layoutSubviews]; self.playerLayer.frame = self.bounds; }
第一步:在UIVIew.h中检查UIView的autoresizing属性
@属性(非primefaces)UIViewAutoresizing autoresizingMask; //简单的resize 默认是UIViewAutoresizingNone
这个属性logging了IB中的“spring和struts”控件,虽然它会带你进行一些实验来获得你想要的结果。
Dunc的回答对我不起作用。 我发现了一个更简单的解决scheme:我只需要在UIView中更改AVPlayerLayer的框架就可以了:
avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
在这个博客中说,一个视图的框架也影响到它的层。
当你改变一个视图的框架时,它只是改变图层的框架。
对于这种情况,这是不正确的。
要访问playerLayer
,您需要循环访问videoHolderView.layer.sublayers
并更改每个。
这就是我在Swift 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 } }
发现Marco Santarossa的一篇很棒的文章,展示了多种修复方法。 https://marcosantadev.com/calayer-auto-layout-swift/
我用他的第一个build议来重置viewDidLayoutSubViews()事件期间的图层框架。
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() playerLayer.frame = view.layer.bounds }
任何人searchXamarin版本,我正在寻找
不要将AVPlayerLayer添加为子图层,而是将图层设置为Avplayer图层
[Export("layerClass")] public static Class LayerClass() { return new Class(typeof(AVPlayerLayer)); }
以下行设置图层
(this.Layer as AVPlayerLayer).Player = _player; // Acplayer
我有这个问题在Swift 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) }