Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube player opening unnecessarily during scrolling of CollectionView

I am working on a chatbot where the different type of response comes from the server and I display the response using UICollectionView cells in chat screen. Different type of cells presents according to server response. when server response with playing video, I am presenting the cell that contains youtube player. I am using https://github.com/kieuquangloc147/YouTubePlayer-Swift. The issue is when I scroll chat screen (collectionView) youtube player is opening again and again. Sometimes it is blocking all the UI element and stop scrolling. I tried different methods but can't able to resolve it. Here is the code: PlayerView:

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 (Which I present in collectionView wthe hen server responds for video):

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

}

Here is how I am presenting the YouTubePlayerCell in cellForItemAt method of UICollectionView

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
                }
            }

Full Source Code can be found here: https://github.com/imjog/susi_iOS/tree/ytplayer

like image 894
Jogendra Kumar Avatar asked Jul 13 '18 05:07

Jogendra Kumar


1 Answers

I can see that in the below code

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

you are calling loadVideo method, which is responsible for showing the player. So while scrolling you are reusing the cell and it calls loadVideo method and present the player. so the solution is don't start playing the video by default on displaying the cell, provide a play/pause button on the cell video overlay and on clicking the the button start playing the video. If my analysis is wrong please let me know, what exact issue you have.

like image 157
vivekDas Avatar answered Nov 02 '22 09:11

vivekDas