当UIView帧更改时,视图内的AVPlayer图层不会调整大小

the*_*ncs 52 objective-c calayer 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;
Run Code Online (Sandbox Code Playgroud)

然后,稍后,我将更改videoHolderView框架的大小和位置:

[videoHolderView setFrame:CGRectMake(0, 0, 768, 502)];
Run Code Online (Sandbox Code Playgroud)

此时,我需要avPlayer调整大小到这些相同的维度.这不会自动发生 - avPlayer在videoHolderView中保持小尺寸.

如果有人可以提供帮助,我真的很感激任何建议.

多谢你们.

Mar*_*son 63

  playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
Run Code Online (Sandbox Code Playgroud)

  • 这不能解决问题并裁剪视频 (4认同)
  • `AVLayerVideoGravityResizeAspectFit` 不存在 - 它是 `AVLayerVideoGravityResizeAspect` (3认同)
  • 您可以使用AspectFit而不是AspectFill (2认同)

Sam*_*Sam 26

将@ Suran的解决方案转换为Swift 3:

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

import UIKit
import AVFoundation

class AVPlayerView: UIView {
    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用界面构建器添加一个简单的UIView,并将其类更改为刚刚创建的类:AVPlayerView

将常规UIView的类更改为AVPlayerView

然后,为该视图制作一个出口.称之为avPlayerView

@IBOutlet weak var avPlayerView: AVPlayerView!
Run Code Online (Sandbox Code Playgroud)

现在,您可以在viewcontroller中使用该视图并访问其avlayer,如下所示:

let avPlayer = AVPlayer(url: video)
let castedLayer = avPlayerView.layer as! AVPlayerLayer
castedLayer.player = avPlayer
avPlayer.play()
Run Code Online (Sandbox Code Playgroud)

现在,该层将遵循约束,就像常规图层一样.无需手动更改边界或大小.


Sur*_*ran 21

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

+ (Class)layerClass
{
     return [AVPlayerLayer class];
}
Run Code Online (Sandbox Code Playgroud)

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

[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你;-)


the*_*ncs 16

最后,我通过将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];
Run Code Online (Sandbox Code Playgroud)


小智 9

发现了Marco Santarossa的精彩文章,其中展示了多种修复方法。https://marcosantadev.com/calayer-auto-layout-swift/

我使用他的第一个建议在viewDidLayoutSubViews()事件期间重置图层框架。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    playerLayer.frame = view.layer.bounds
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*ton 7

您可以通过覆盖-layoutSubviews方法来更改图层的框架:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.playerLayer.frame = self.bounds;
}
Run Code Online (Sandbox Code Playgroud)


Pix*_*xel 7

在 Swift 4 中使用

    playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
Run Code Online (Sandbox Code Playgroud)

AVLayerVideoGravity您想要的任何财产。