Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VideoNode Tap to Fullscreen with Smooth Instagram-like Transition #2117

Open
abbasnaqvi200 opened this issue Sep 26, 2024 · 0 comments
Open

Comments

@abbasnaqvi200
Copy link

abbasnaqvi200 commented Sep 26, 2024

Hey, could you please help me with code for displaying videos in a table view using ASVideoNode? When the video is tapped, it should transition smoothly to fullscreen, similar to Instagram’s video experience. I’d also like the video to continue playing from where it left off during the transition. Smooth animation is essential for a seamless user experience.

My Video Cell Code is:-

class WallVideoNode: ASCellNode {

let videoNode = ASVideoNode()
let muteButton = ASButtonNode()

var size = CGSize(width:UIScreen.main.bounds.width, height: UIScreen.main.bounds.width)

override init() {
    super.init()
    setupVideoNode()
}

init(size : CGSize) {
    super.init()
    self.size = size
    setupVideoNode()
}

var videoURL : URL?
var mediaFile : MediaFilePath?
var isPlayingOnFullScreen = false


private func setupVideoNode() {
    videoNode.delegate = self
    videoNode.shouldAutorepeat = true
    //videoNode.shouldAutoplay = true
    videoNode.backgroundColor = .black
    videoNode.muted = WallView.currentMuteStatus
    addSubnode(videoNode)
    addSubnode(muteButton)
}

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
    
    return LayoutSpec {
        videoNode.preferredSize(size).overlay {
            
            InsetLayout(insets: UIEdgeInsets(top: .infinity, left: .infinity, bottom: 10, right: 10)) {
                muteButton.preferredSize(CGSize(width: 30, height: 30))
            }
        }
    }
}

func configureVideo(with mediaFile: MediaFilePath) {
    self.mediaFile = mediaFile
   
    if let url = URL.init(string: mediaFile.wall_Media_Path ?? "") {
        self.videoURL = url
        
        DispatchQueue.global(qos: .background).async {
            let asset = AVAsset(url: url)
            asset.loadValuesAsynchronously(forKeys: ["playable"], completionHandler: {
                DispatchQueue.main.async {
                    asset.cancelLoading()
                    self.videoNode.asset = asset
                }
            })
        }
    }
    
    let placeholder =  mediaFile.gcs_Video_Placeholder ?? ""
    
    self.setWallImage(placeholder, media: mediaFile)

    videoNode.gravity = AVLayerVideoGravity.resizeAspectFill.rawValue // Set Aspect Fill
    muteButton.tintColor = .white
    muteButton.cornerRadius = 15
    videoNode.muted = WallView.currentMuteStatus
    muteButton.isSelected = WallView.currentMuteStatus
    muteButton.backgroundColor = UIColor.black.withAlphaComponent(0.3)
    let size = CGSize(width: 12, height: 12)
    muteButton.setImage(UIImage(named: "ct_unmute_white")?.resize(targetSize:size ), for: .normal)
    muteButton.setImage(UIImage(named: "ct_mute_white")?.resize(targetSize: size), for: .selected)
    muteButton.addTarget(self, action: #selector(muteVideo), forControlEvents: .touchUpInside)
}

func setMuteUnmute() {
    muteButton.isSelected = WallView.currentMuteStatus
    videoNode.muted = WallView.currentMuteStatus
}

@objc func muteVideo() {
    muteButton.isSelected = !muteButton.isSelected
    videoNode.muted = muteButton.isSelected
    WallView.currentMuteStatus = muteButton.isSelected
}

func playVideo() {
    videoNode.play()
}

func pauseVideo() {
    videoNode.pause()
}

}

extension WallVideoNode : ASVideoNodeDelegate {

// ASVideoNodeDelegate method
func didTap(_ videoNode: ASVideoNode) {
    
    if isPlayingOnFullScreen {
        
        self.closestViewController?.presentedViewController?.dismiss(animated: true)
        self.insertSubnode(videoNode, at: 0)
        self.isPlayingOnFullScreen = false
        
    } else {
        isPlayingOnFullScreen = true
        print("Video node tapped!")
        ///videoNode.gravity = AVLayerVideoGravity.resizeAspect.rawValue // Set Aspect Fill
        guard let asset = videoNode.asset else { return }
        //pauseVideo() // Pause the current video and save playback time
        self.transitionToFullScreen()
    }
}

}

extension WallVideoNode {

func transitionToFullScreen() {
    // 1. Get the snapshot of the video node
    guard let vc = self.closestViewController else {return}
    
    
    let heroId = "cell\(1)"
    
    // Setting Hero ID for transition
    let fullScreenSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    videoNode.frame = CGRect(origin: .zero, size: fullScreenSize)
    videoNode.layoutIfNeeded()
    
    videoNode.view.hero.id = heroId
    
    let detailVC = FullScreenVideoViewController(videoNode: videoNode)
    detailVC.modalPresentationStyle = .overFullScreen
    detailVC.hero.isEnabled = true
    //detailVC.videoNode.view.hero.id = heroId

    detailVC.dismissUpdate = {
        self.insertSubnode(self.videoNode, at: 0)
        self.isPlayingOnFullScreen = false
    }
    
    vc.present(detailVC, animated: false, completion: nil)

}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant