Ios 带其他视图的UITableViewCell内的AVPlayer自动布局

Ios 带其他视图的UITableViewCell内的AVPlayer自动布局,ios,swift,uitableview,autolayout,avplayer,Ios,Swift,Uitableview,Autolayout,Avplayer,我有一个UITableViewCell,它有一个UILabel和一个AVPlayer,可以播放我需要实现的在线视频。问题是AVPlayer无法使用自动布局正确显示视频 我相信对于混合约束和框架布局,有一些方法可以实现UIView。我认为这个问题还有很多:视频没有加载到init上这一事实似乎存在问题 UITableViewCell import UIKit import AVKit import AVFoundation class PlayerView: UIView { var pl

我有一个UITableViewCell,它有一个UILabel和一个AVPlayer,可以播放我需要实现的在线视频。问题是AVPlayer无法使用自动布局正确显示视频

我相信对于混合约束和框架布局,有一些方法可以实现UIView。我认为这个问题还有很多:视频没有加载到init上这一事实似乎存在问题

UITableViewCell

import UIKit
import AVKit
import AVFoundation

class PlayerView: UIView {
    var player: AVPlayer? {
        get {
            return playerLayer.player
        }
        set {
            playerLayer.videoGravity = .resizeAspect
            playerLayer.player = newValue
        }
    }

    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    override static var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}

class CustomTableCell: UITableViewCell {
    let titleView = UILabel()
    let containerView = UIView()
    let playerView = PlayerView()
    required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)}
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        titleView.text = "Title"
        titleView.translatesAutoresizingMaskIntoConstraints = false

        contentView.clipsToBounds = true
        containerView.clipsToBounds = true
        contentView.addSubview(containerView)
        containerView.translatesAutoresizingMaskIntoConstraints = false
        //contentView.layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        var lg = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            containerView.topAnchor.constraint(equalTo: lg.topAnchor),
            containerView.leadingAnchor.constraint(equalTo: lg.leadingAnchor),
            containerView.trailingAnchor.constraint(equalTo: lg.trailingAnchor),
            containerView.bottomAnchor.constraint(equalTo: lg.bottomAnchor)
        ])

        containerView.addSubview(titleView)
        containerView.layoutMargins = UIEdgeInsets(top: 15, left: 17, bottom: 15, right: 17)
        lg = containerView.layoutMarginsGuide

        playerView.translatesAutoresizingMaskIntoConstraints = false
        containerView.addSubview(playerView)
        NSLayoutConstraint.activate([
            titleView.topAnchor.constraint(equalTo: lg.topAnchor),
            titleView.leadingAnchor.constraint(equalTo: lg.leadingAnchor),
            titleView.trailingAnchor.constraint(equalTo: lg.trailingAnchor),
//            titleView.bottomAnchor.constraint(equalTo: lg.bottomAnchor),

            playerView.topAnchor.constraint(equalTo: titleView.bottomAnchor),
            playerView.leadingAnchor.constraint(equalTo: lg.leadingAnchor),
            playerView.trailingAnchor.constraint(equalTo: lg.trailingAnchor),
            playerView.bottomAnchor.constraint(equalTo: lg.bottomAnchor)
        ])
    }
}
我已经在我的视图控制器中设置了UITableView,但主要问题是UITableViewDataSource cellForRowAt:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReuseableCell(withIdentifier: "cell") as! CustomTableCell
    let url = NSURL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
    let avPlayer = AVPlayer(url: url! as URL)
    cell.playerView.playerLayer.player = avPlayer
    return cell
}
但我没有看到视频。很明显,有一个类似willLayoutSubviews之类的函数,但是我如何打破标题视图的约束,用AVPlayerLayer或类似的东西来约束,这样我就可以看到视频了

一般来说,我如何看到AVPlayer或自定义UITableViewCell中具有其他自动布局视图的任何播放器


编辑1:@ugur给出的答案是正确的,因为AVPlayer需要调整大小。使用leadngAnchor和trailingAnchor扩展视图无法解决此问题,因为仅扩展了当前视图的大小


使用centerXAnchor、widthAnchor和heightAnchor将有效。centerXAnchor将使您的播放器在视图中居中。

您需要告诉autolayout如何计算playerView高度。 您可以尝试以下选项:

  • 将恒定高度设置为playerView

    playerView.heightAnchor.constraint(equalToConstant: 100)
    
    playerView.heightAnchor.constraint(equalTo: playerView.widthAnchor, multiplier: 1.0)
    
  • 或者将纵横比设置为playerView

    playerView.heightAnchor.constraint(equalToConstant: 100)
    
    playerView.heightAnchor.constraint(equalTo: playerView.widthAnchor, multiplier: 1.0)
    
  • 因此,autolayout将知道如何定位playerView。否则,playerView高度将为0

    建议:


    不要在
    cellFor
    中创建
    AVPlayer
    ,而是在cell init或
    awakeFromNib
    中创建(如果使用了脚本)。因此,
    AVPlayer
    也可以重用。只需使用新url或
    playerItem
    重置设置即可。您也可以根据您的情况使用播放或暂停。但是不要每次调用
    cellFor
    时都重新创建
    AVPlayer

    因此,您的主要问题是无法在单元格内看到播放机。我修改了你们的一些代码,然后它也显示和播放视频

    注意:这是非常基本的代码,我相信您将能够根据您的要求进一步改进它

    您的
    PlayerView
    保持不变,更改如下。我添加了新的方法
    configureFor
    ,它将只获取url作为参数和播放器的设置

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableCell
        let url = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
        cell.configureFor(url!)
        return cell
    }
    
    以下是您的单元格代码。 在这里,我将UI设置代码移动到一个公共函数
    commonInit()
    ,然后按如下方式使用它

        class CustomTableCell: UITableViewCell {
    
        let titleView = UILabel()
        let containerView = UIView()
        let playerView = PlayerView()
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            commonInit()
        }
    
        func commonInit() {
            titleView.text = "Title"
            titleView.translatesAutoresizingMaskIntoConstraints = false
    
            contentView.clipsToBounds = true
            containerView.clipsToBounds = true
            containerView.backgroundColor = .orange
            contentView.addSubview(containerView)
            containerView.translatesAutoresizingMaskIntoConstraints = false
            //contentView.layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
            var lg = contentView.layoutMarginsGuide
            NSLayoutConstraint.activate([
                containerView.topAnchor.constraint(equalTo: lg.topAnchor),
                containerView.leadingAnchor.constraint(equalTo: lg.leadingAnchor),
                containerView.trailingAnchor.constraint(equalTo: lg.trailingAnchor),
                containerView.bottomAnchor.constraint(equalTo: lg.bottomAnchor)
            ])
    
            containerView.addSubview(titleView)
            containerView.layoutMargins = UIEdgeInsets(top: 15, left: 17, bottom: 15, right: 17)
            lg = containerView.layoutMarginsGuide
    
            playerView.translatesAutoresizingMaskIntoConstraints = false
            containerView.addSubview(playerView)
            NSLayoutConstraint.activate([
                titleView.topAnchor.constraint(equalTo: lg.topAnchor),
                titleView.leadingAnchor.constraint(equalTo: lg.leadingAnchor),
                titleView.trailingAnchor.constraint(equalTo: lg.trailingAnchor),
                //            titleView.bottomAnchor.constraint(equalTo: lg.bottomAnchor),
    
                playerView.topAnchor.constraint(equalTo: titleView.bottomAnchor),
                playerView.leadingAnchor.constraint(equalTo: lg.leadingAnchor),
                playerView.trailingAnchor.constraint(equalTo: lg.trailingAnchor),
                playerView.bottomAnchor.constraint(equalTo: lg.bottomAnchor)
            ])
        }
    
        func configureFor(_ url: URL) {
            let avPlayer = AVPlayer(url: url)
            self.playerView.playerLayer.player = avPlayer
            self.playerView.playerLayer.player?.play()
        }
    }
    

    你能分享一些屏幕截图吗?@Niraj_iOS我只看到文本。视频不会出现。事实上,即使它做了它没有做的,如果用户重新定位了设备,然后视频就会变成一场灾难。你可以将
    ui视图
    放在情节提要中,并在该视图中添加播放器programatically@Yoomama请看下面的答案,我希望能解决您的问题。@Yoomama您是否检查了下面的答案?如果我同时设置了高度和宽度锚点(连同顶部和底部锚(idk??),视频会失真吗?另外,我把它放在cellFor中,因为我正在用它链接一个服务器,需要某种索引来使用cellFor将一组数据链接到cellFor。我还能怎么做呢?你介意举个例子说明我如何在cellFor的init中而不是cellFor中实例化吗?非常缺乏经验抱歉,它不起作用。我感觉到的担心是引导anchor和trailingAnchor。知道这个UIView不是一个正常的UIView。你必须增加AVPlayer的大小,这需要高度和宽度锚。好吧,因为我在本地尝试过,它正在显示播放器,而且视频正在播放,我所做的一切在模拟器上看到的是iOS 13 iPhone 11 Pro Max上的橙色单元格。请检查@ugur给出的答案。不要粗鲁,但你的init没有什么帮助。将init移动到自定义函数中不会放大PlayerView。你需要这些锚来显示视频。在初始化后安装视频对任何视图都不起作用NL除非重新实例化视图。更改还在于如何配置单元格。请在索引路径处查看单元格中的行