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

Yoo*_*ama 5 uitableview ios avplayer autolayout swift

我有一个 UITableViewCell,它有一个 UILabel 和一个 AVPlayer,可以播放我需要实现的在线视频。问题是Apple提供的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)
        ])
    }
}
Run Code Online (Sandbox Code Playgroud)

我在视图控制器中设置了 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
}
Run Code Online (Sandbox Code Playgroud)

但我没有看到视频。显然,有一个像 willLayoutSubviews 这样的函数或类似的函数,但是我如何打破标题视图的约束以与 AVPlayerLayer 或类似的函数进行约束,以便我可以看到视频?

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


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

使用 centerXAnchor、widthAnchor 和 heightAnchor 即可。centerXAnchor 将使您的玩家在视图中居中。

ugu*_*gur 1

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

  1. 为playerView设置恒定高度

    playerView.heightAnchor.constraint(equalToConstant: 100)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或为playerView设置宽高比

    playerView.heightAnchor.constraint(equalTo: playerView.widthAnchor, multiplier: 1.0)
    
    Run Code Online (Sandbox Code Playgroud)

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

建议:

不要在单元格初始化中创建AVPlayercellFor而是在单元格初始化中创建awakeFromNib(如果使用故事板)。所以AVPlayer也可以重复使用。只需使用新的 url 或 .reset 设置即可playerItem。您还可以根据您的情况使用播放或暂停。但只是不要重新创建AVPlayer每次cellFor被调用的时间。