UICollectionView scrollToItem not working when multiple cell visible on screen and cell size small iOS

42 Views Asked by At

I have set up the UICollectionView with the DetailMediaCell XIB. If multiple answers are available, then a sub UICollectionView is shown, already set up in the XIB.

Everything works fine, but when we open the view controller and check if there's a video, it should start playing from the beginning. However, it always starts from the first index automatically.

Additionally, when the video finishes, I've set up the scrollToItem function, but it's not working in my case. I suspect it's due to the size of the cell, which prevents it from scrolling to the first index.

For more details, please refer to the attached screenshot and code.

ScreenShot

Code:-

    import UIKit
    import AVFoundation

    class DetailMediaCell: UICollectionViewCell {
        
    @IBOutlet weak var mainVideoVwForPlay: UIView!
    @IBOutlet weak var vwForAnswerCollectionVw: UIView!
    @IBOutlet weak var heightAnswerCollectionVw: NSLayoutConstraint!
    @IBOutlet weak var answerCollectionVw: UICollectionView!
        
    var arrPlayer:[AudioPlayer] = []
    
    var subIndex:Int = 0
    var mainIndex:Int = -1
    
    var media: String?
    var playerItem: CachingPlayerItem?
    var player:AudioPlayer = AudioPlayer()
    var playerLayer:AVPlayerLayer = AVPlayerLayer()
        
    var subAnswerArray = [String]()
    
    override func awakeFromNib() {
        super.awakeFromNib()
        registerUserAnswersCollectionView()
    }
    
    func registerUserAnswersCollectionView(){
        answerCollectionVw.register(UINib(nibName: "MultiCell", bundle: nil), forCellWithReuseIdentifier: "MultiCell")
        answerCollectionVw.dataSource = self
        answerCollectionVw.delegate = self
    }
    
    func getAnswersForQuestion() {
        heightAnswerCollectionVw.constant = subAnswerArray.count != 0 ? 110 : 0
        
        self.arrPlayer = subAnswerArray.map({ hpmr in
            return AudioPlayer()
        })
        
        playZeroIndexItemIfContainsMedia()
        }
    }

    extension DetailMediaCell {
    
    func initCell(media: String,audioPlayer:AudioPlayer,subIndexs:Int,mainIndexs:Int) {
        mainIndex = mainIndexs
        subIndex = subIndexs
        player = audioPlayer
        self.setupVideoPlayer(media: media)
    }
    
    func setupVideoPlayer(media: String?) {
        if(player.playerItem == nil) {
            if media != "" {
                player.startPlayback(with: URL.init(string: media ?? "")!)
                playerItem = player.playerItem
                playerLayer = AVPlayerLayer(player: player)
                playerLayer.frame = self.bounds
                
                mainVideoVwForPlay.layer.sublayers?.forEach({ ccc in
                    ccc.removeFromSuperlayer()
                })
                
                mainVideoVwForPlay.layer.addSublayer(playerLayer)
                
                let recordingSession:AVAudioSession = AVAudioSession.sharedInstance()
                do {
                    try recordingSession.overrideOutputAudioPort(.speaker)
                    try recordingSession.setActive(true)
                } catch {
                    print(error.localizedDescription)
                }
                
                NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
            }
        } else {
            playerLayer.frame = self.bounds
        }
    }
    
    func playerStart(mainIndexs:Int,subIndexs:Int) {
        mainIndex = mainIndexs
        subIndex = subIndexs
        self.player.isMuted = LocalStore.shared.isMutePressed
        self.player.play()
    }
    
    func playerInvalidate() {
        if(player.rate == 1) {
            player.pause()
            self.player.seek(to: .zero)
        }
    }
    
    func playerInvalidateWithnil() {
        if(player.rate == 1) {
            player.pause()
            player = AudioPlayer()
        }
    }
    
    @objc func didPlayToEnd(notification: NSNotification) {
        if let item = notification.object as? AVPlayerItem, let currentItem = player.currentItem, item == currentItem {
            self.player.pause()
            self.player.seek(to: .zero)
            DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { [self] in
                if subAnswerArray.count >  0 {
                    playerItemFinish(isMediaUrl: media ?? "", mainIndexs: mainIndex, subIndexs: subIndex)
                }
            })
             }
          }
      } 

       extension DetailMediaCell : UICollectionViewDataSource , UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return subAnswerArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MultiAnswersCell", for: indexPath) as! MultiAnswersCell
        if subIndex == indexPath.item {
            cell.vwForHighlight.isHidden = false
        }else{
            cell.vwForHighlight.isHidden = true
        }
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 85, height: collectionView.frame.height)
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let firstVisibleCellIndexPath = answerCollectionVw.indexPathsForVisibleItems.first
        if let firstVisibleCellIndexPath = firstVisibleCellIndexPath {
            DispatchQueue.main.async { [self] in
                subIndex = firstVisibleCellIndexPath.item
                print("Visible Index = ",subIndex)
            }
        }
    }
        
    func playZeroIndexItemIfContainsMedia() {
        DispatchQueue.main.asyncAfter(deadline: .now()+0.3, execute: { [self] in
            playerItemFinish(isMediaUrl: media ?? "", mainIndexs: mainIndex, subIndexs: subIndex)
          })
        }
     }

     extension DetailMediaCell {
    func playerItemFinish(isMediaUrl: String, mainIndexs: Int, subIndexs: Int) {
        let item = subIndexs + 1
        let indexPath = IndexPath(item: subIndexs, section: 0)
        if item < answerCollectionVw.numberOfItems(inSection: 0) {
            subIndex = item
            answerCollectionVw.scrollToItem(at: indexPath, at: .top, animated: false)
         }
       }
     }

0

There are 0 best solutions below