我正在使用UITableViewCell的子类,该子类根据表视图单元格所显示的媒体类型创建UIView的两个子类中的一个-UIImageView或我自己的利用AVPlayerLayer的UIView子类。表格视图单元格应根据UIView子类的内容模式(.scaleAspectFit)调整自身大小。当媒体是在UIImageView中显示的图像时,我的代码有效,但是当媒体是使用AVPlayerLayer在UIView的子类中显示的电影时,则无效,在这种情况下,表视图单元格为窄行。我知道电影正在播放,因为我听到它在播放。
该如何解决?
class MediaTableViewCell: UITableViewCell {
var mediaView: UIView!
var audioPlayer: AVAudioPlayer!
var mediaImageView: UIImageView!
var playerView: PlayerView!
var playerLooper: AVPlayerLooper!
func setMedia(mediaType: MediaType?, mediaURL: URL?) {
// mediaType and mediaURL are always both nil or both not nil.
if let mediaType = mediaType, let mediaURL = mediaURL {
mediaView?.removeFromSuperview()
switch mediaType {
case .music:
let image = UIImage(named: "audio.png")
mediaImageView = UIImageView()
mediaImageView.contentMode = .scaleAspectFit
mediaImageView.image = image
mediaView = mediaImageView
playerView = nil
audioPlayer = try? AVAudioPlayer(contentsOf: mediaURL)
audioPlayer?.play()
case .image:
let image = UIImage(contentsOfFile: mediaURL.path)
mediaImageView = UIImageView()
mediaImageView.contentMode = .scaleAspectFit
mediaImageView.image = image
mediaView = mediaImageView
playerView = nil
case .movie:
playerView = PlayerView()
playerView.contentMode = .scaleAspectFit
mediaView = playerView
mediaImageView = nil
let playerItem = AVPlayerItem(url: mediaURL)
playerView.player = AVQueuePlayer()
playerLooper = AVPlayerLooper(player: playerView.player!, templateItem: playerItem)
playerView.player!.play()
}
} else {
let image = UIImage(named: "vision.png")!
mediaImageView = UIImageView()
mediaImageView.contentMode = .scaleAspectFit
mediaImageView.image = image
mediaView = mediaImageView
playerView = nil
}
mediaView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(mediaView)
NSLayoutConstraint(item: mediaView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leadingMargin, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: mediaView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailingMargin, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: mediaView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .topMargin, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: mediaView, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottomMargin, multiplier: 1, constant: 0).isActive = true
contentView.setNeedsLayout()
contentView.layoutIfNeeded()
contentView.setNeedsDisplay()
}
}
class PlayerView: UIView {
var player: AVQueuePlayer? {
get {
return playerLayer.player as? AVQueuePlayer
}
set {
playerLayer.player = newValue
}
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
// Override UIView property
override static var layerClass: AnyClass {
return AVPlayerLayer.self
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
...
case 2:
let cell = tableView.dequeueReusableCell(withIdentifier: "mediaCell") as! MediaTableViewCell
tableView.beginUpdates()
if let detailItem = detailItem {
cell.setMedia(mediaType: detailItem.mediaType, mediaURL: detailItem.mediaURL)
} else {
cell.setMedia(mediaType: nil, mediaURL: nil)
}
tableView.endUpdates()
tableView.setNeedsLayout()
tableView.layoutIfNeeded()
tableView.setNeedsDisplay()
view.setNeedsLayout()
view.layoutIfNeeded()
view.setNeedsDisplay()
return cell
default:
fatalError()
}
fatalError()
}