UITableViewCell内的AVPlayer以及其他视图自动布局

问题描述 投票:0回答:2

我有一个UITableViewCell,它具有UILabel和AVPlayer,可以播放我需要实现的在线视频。问题是Apple gives无法使用自动布局的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内具有其他自动布局视图的任何播放器?

ios swift uitableview autolayout avplayer
2个回答
0
投票

您需要告诉自动布局,如何计算playerView的高度。您可以尝试以下选项:

  1. 为playerView设置恒定的高度

    playerView.heightAnchor.constraint(equalToConstant: 100)
    
  2. 或为playerView设置长宽比

    playerView.heightAnchor.constraint(equalTo: playerView.widthAnchor, multiplier: 1.0)
    

所以自动布局会知道如何放置playerView。否则playerView的高度将为0。

建议:

不要在AVPlayer中创建cellFor,而要在单元格init或awakeFromNib中创建(如果使用情节提要)。因此,AVPlayer也将可重用。只需使用新的URL或playerItem重置设置即可。您还可以根据情况使用播放或暂停。但是只是不要每次调用AVPlayer时都重新创建cellFor


0
投票

希望您度过了愉快的一周!

因此,您的主要问题是您无法看到玩家在牢房内。我已经修改了一些代码,然后它也显示并播放了视频。

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

您的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()
    }
}

希望我回答您的问题还为时不晚。

祝您编程愉快,祝您度过一个愉快的一周,并在2020年完成了。

© www.soinside.com 2019 - 2024. All rights reserved.