ios - 滚动 CollectionView 期间不必要地打开 YouTube 播放器

标签 ios swift uicollectionview uicollectionviewcell youtubeplayer

我正在开发一个聊天机器人,其中不同类型的响应来自服务器,我在聊天屏幕中使用 UICollectionView 单元显示响应。根据服务器响应显示不同类型的单元格。当服务器响应播放视频时,我会显示包含 youtube 播放器的单元格。我正在使用 https://github.com/kieuquangloc147/YouTubePlayer-Swift .问题是当我滚动聊天屏幕 (collectionView) 时,youtube 播放器一次又一次打开。有时它会阻止所有 UI 元素并停止滚动。我尝试了不同的方法,但无法解决。这是代码: 播放器 View :

import UIKit

class PlayerView: UIView, YouTubePlayerDelegate {

    override init(frame: CGRect) {
        super.init(frame: frame)
        addYotubePlayer()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // youtube player
    lazy var youtubePlayer: YouTubePlayerView = {
        let viewFrame = UIScreen.main.bounds
        let player = YouTubePlayerView(frame: CGRect(x: 0, y: 0, width: viewFrame.width - 16, height: viewFrame.height * 1/3))
        player.delegate = self
        return player
    }()

    // used as an overlay to dismiss the youtube player
    let blackView = UIView()

    // youtube player loader
    lazy var playerIndicator: UIActivityIndicatorView = {
        let indicator = UIActivityIndicatorView()
        indicator.activityIndicatorViewStyle = .whiteLarge
        indicator.hidesWhenStopped = true
        return indicator
    }()

    // shows youtube player
    func addYotubePlayer() {
        if let window = UIApplication.shared.keyWindow {
            blackView.frame = window.frame
            self.addSubview(blackView)
            blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
            let tap = UITapGestureRecognizer(target: self, action: #selector(handleDismiss))
            tap.numberOfTapsRequired = 1
            tap.cancelsTouchesInView = false
            blackView.addGestureRecognizer(tap)


            let centerX = UIScreen.main.bounds.size.width / 2
            let centerY = UIScreen.main.bounds.size.height / 2

            blackView.addSubview(playerIndicator)
            playerIndicator.center = CGPoint(x: centerX, y: centerY)
            playerIndicator.startAnimating()

            blackView.addSubview(youtubePlayer)
            youtubePlayer.center = CGPoint(x: centerX, y: centerY)

            blackView.alpha = 0
            youtubePlayer.alpha = 0

            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                self.blackView.alpha = 1
                self.youtubePlayer.alpha = 1
            }, completion: nil)
        }
    }

    func play(_ videoID: String) {
        youtubePlayer.loadVideoID(videoID)
    }

    @objc func handleDismiss() {
        blackView.removeFromSuperview()
        UIApplication.shared.keyWindow?.viewWithTag(24)?.removeFromSuperview()
        UIApplication.shared.keyWindow?.removeFromSuperview()
    }

    func playerReady(_ videoPlayer: YouTubePlayerView) {
        self.playerIndicator.stopAnimating()
    }

    func playerStateChanged(_ videoPlayer: YouTubePlayerView, playerState: YouTubePlayerState) {
    }

    func playerQualityChanged(_ videoPlayer: YouTubePlayerView, playbackQuality: YouTubePlaybackQuality) {
    }

}

YouTubePlayerCell(当服务器响应视频时,我在 collectionView 中呈现):

import UIKit

class YouTubePlayerCell: ChatMessageCell {

    var player: PlayerView = PlayerView(frame: UIScreen.main.bounds)

    override func setupViews() {
        super.setupViews()
        setupCell()
    }

    func setupCell() {
        messageTextView.frame = CGRect.zero
        textBubbleView.frame = CGRect.zero
    }

    func loadVideo(with videoID: String) {
        player.tag = 24
        UIApplication.shared.keyWindow?.addSubview(player)
        player.play(videoID)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        player.removeFromSuperview()
        UIApplication.shared.keyWindow?.viewWithTag(24)?.removeFromSuperview()
    }

}

这是我在 UICollectionViewcellForItemAt 方法中呈现 YouTubePlayerCell 的方式

let message = messages[indexPath.row]
    if message.actionType == ActionType.video_play.rawValue {
                if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ControllerConstants.youtubePlayerCell, for: indexPath) as? YouTubePlayerCell {
                    self.resignResponders()
                    if let videoId = message.videoData?.identifier {
                        cell.loadVideo(with: videoId)
                    }
                    return cell
                }
            }

完整的源代码可以在这里找到:https://github.com/imjog/susi_iOS/tree/ytplayer

最佳答案

我可以在下面的代码中看到

if let videoId = message.videoData?.identifier {
                        cell.loadVideo(with: videoId)
                    }

您正在调用 loadVideo 方法,该方法负责显示播放器。 因此,在滚动时您正在重复使用该单元格,它会调用 loadVideo 方法并呈现播放器。所以解决方案是在显示单元格时不默认开始播放视频,在单元格视频叠加层上提供一个播放/暂停按钮,然后单击该按钮开始播放视频。 如果我的分析有误,请告诉我您遇到的具体问题。

关于ios - 滚动 CollectionView 期间不必要地打开 YouTube 播放器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51317969/

相关文章:

swift - Swift 中 HomeVC 退出按钮的导航 rootViewController 问题

ios - 为什么 UITableViewCell 有一个 contentView 属性?

javascript - iOS 和 Android 中滚动页面的触摸事件偏移不正确

ios - 需要想法 : Ways to display list of list of data in iOS

Swift:如何检查协议(protocol)的可用性?

ios - 如何使用PHAsset获取[PHAssetCollection]

ios - UICollectionView 单元格留下巨大间隙所有设置设置为 0

ios - collectionView 中每个单元格的时间戳

ios - 从 Swift 中的背景颜色确定文本颜色?

swift - 设置高度: TableViewCells with custom Nib that are different sizes