我有一个视频播放器和一个覆盖它的UIView,我在视频区域中使用它作为Gesture Recognition。我这样做是为了让你可以点击视频的不同区域来播放,倒带和做其他功能。
目前,这在景观中工作得很好,但如果我将设备旋转到肖像。UIView不调整大小,但视频播放器调整大小。我试图以编程方式使用约束,但我不知道如何访问视频播放器的NSLayout锚。
我有一个检索视频帧大小的函数,我当前使用该函数将UIView设置为视频播放器的大小。
下面的代码可以复制到一个项目中,以播放视频并显示我想要调整的UIView。您只需将UIView添加到UIViewController情节提要中。代码不包含GestureRecogniser部件。
import UIKit
import AVFoundation
class ViewController: UIViewController {
let controlContainerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(white: 0, alpha: 1)
return view
}()
let activityIndicatorView: UIActivityIndicatorView = {
let aiv = UIActivityIndicatorView(style: .whiteLarge)
aiv.translatesAutoresizingMaskIntoConstraints = false
aiv.startAnimating()
return aiv
}()
@IBOutlet weak var videoContainer: UIView!
var player: AVPlayer?
var playerLayer: AVPlayerLayer?
var tapRegionBounds: UIView!
var tapRegionAreaCreated: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let urlString = "https://www.radiantmediaplayer.com/media/bbb-360p.mp4"
videoPlayer(filename: urlString)
player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
}
override func viewDidAppear(_ animated: Bool) {
self.playerLayer?.frame = CGRect(x: 0, y: 0, width: self.videoContainer.frame.width, height: self.videoContainer.frame.height)
updateTapRegions()
}
func videoPlayer(filename: String){
let item = AVPlayerItem(url: URL(string: filename)!)
player = AVPlayer(playerItem: item)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.videoGravity = .resizeAspect
playerLayer?.frame = CGRect(x: 0, y: 0, width: self.videoContainer.frame.width, height: self.videoContainer.frame.height)
videoContainer.layer.addSublayer(playerLayer!)
player?.play()
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "currentItem.loadedTimeRanges" {
activityIndicatorView.stopAnimating()
controlContainerView.backgroundColor = .clear
}
}
func videoFrame() -> CGRect? {
guard let layer = playerLayer
else { return nil }
let frame = layer.videoRect
if frame.height > 0.0 {
let frameInWindow = layer.convert(frame, to: nil)
return view.convert(frameInWindow, from: nil)
} else {
return nil
}
}
//THE CODE BELOW KIND OF WORKS TO SHOW HOW I WANT IT TO WORK BUT WITHOUT HAVING TO DELETE THE VIEW EACH TIME
func updateTapRegions() {
guard let video = videoFrame() else { return }
let container = videoContainer.bounds
if tapRegionAreaCreated == true {
tapRegionBounds.removeFromSuperview()
tapRegionAreaCreated = false
}
tapRegionBounds = UIView()
tapRegionBounds.frame = CGRect(x: video.minX, y: video.minY, width: container.width, height: video.height)
tapRegionBounds?.alpha = 0.5
tapRegionBounds.backgroundColor = UIColor.red
if tapRegionAreaCreated == false {
view.addSubview(tapRegionBounds)
tapRegionAreaCreated = true
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (context) in
}) { (context) in
self.playerLayer?.frame = CGRect(x: 0, y: 0, width: self.videoContainer.frame.width, height: self.videoContainer.frame.height)
self.updateTapRegions()
}
}
}我尝试在viewWillLayoutSubviews()中更新框架,但也没有任何改变。我知道我的updateTapRegions函数不是正确的方法,但如果有人能给我指出正确的方向,那就太好了,谢谢。
发布于 2019-06-03 10:20:32
不幸的是,您在问题中没有提到如何调整视频容器视图的大小,这一切都依赖于此。但这里有一种可能性。我已经使用自动布局在纵向和横向获得了这些结果:


现在假设我们有一个子层(一个AVPlayerLayer)和一个子视图(点击手势视图)。当然,可以使用自动布局自动调整子视图的大小以适应需要!因此只剩下播放器层;它不会使用自动布局自动调整大小,但您可以在viewDidLayoutSubviews中手动调整它的大小。
发布于 2019-06-03 10:17:24
最后,我将代码从transition function(即使视频播放器正确调整了大小)移动到viewDidLayoutSubviews,这样就可以很好地工作了。此外,我不再需要在每次设备更改方向时创建和删除视图。
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.playerLayer?.frame = CGRect(x: 0, y: 0, width: self.videoContainer.frame.width, height: self.videoContainer.frame.height)
guard let video = videoFrame() else { return }
if tapRegionBounds != nil {
self.tapRegionBounds.frame = CGRect(x: video.minX, y: video.minY, width: video.width, height: video.height)
}
}https://stackoverflow.com/questions/56389571
复制相似问题