简体   繁体   English

点击表格视图单元格中的视频以在视图中打开它 controller

[英]Tapping on a video in a table view cell to open it in a view controller

tl;dr I'm trying to recreate this in the Twitter app: https://i.imgur.com/173CVyM.mp4 tl;博士我正在尝试在 Twitter 应用程序中重新创建它: https://i.imgur.com/173CVyM.mp4

As you can see, Twitter plays a video in the feed (table view cell) and when the video is tapped, the video smoothly transitions into its own view controller, without stopping or buffering the video.如您所见,Twitter 在提要(表格视图单元格)中播放视频,当点击视频时,视频会平滑过渡到自己的视图 controller,无需停止或缓冲视频。

I have the video playing in the feed part done (in the table view cell), but now I'm stuck on how to actually smoothly transition the video into a view controller on tap.我已经完成了提要部分中的视频播放(在表格视图单元格中),但现在我被困在如何将视频平滑地转换为点击时 controller 视图。

At a high level, what do I need to do here?在高层次上,我需要在这里做什么?

My current setup has an AVPlayer instance as part of each table view cell.我当前的设置有一个AVPlayer实例作为每个表格视图单元格的一部分。 Would I pass the AVPlayer instance to the view controller and continue playing the video from there?我会将AVPlayer实例传递给视图 controller 并继续从那里播放视频吗? What about memory management? memory管理呢? I feel like having one AVPlayer instance for each table view cell is going to cause some issues, but I'm not entirely sure.我觉得每个表格视图单元格都有一个AVPlayer实例会导致一些问题,但我并不完全确定。

As a secondary question, if I wanted to ignore the fancy animation/transition, how could I continue playing the video seamlessly in a view controller when it's tapped in the table view cell?作为第二个问题,如果我想忽略花哨的动画/过渡,当在表格视图单元格中点击视频时,如何继续在视图 controller 中无缝播放视频?

To make the transition from your video cell to the player controller you can use your AVPlayerLayer and a custom animation, eg:要从视频单元转换到播放器 controller,您可以使用AVPlayerLayer和自定义 animation,例如:

ViewController.swift ViewController.swift

// Present player controller
let playerViewController = AVPlayerViewController()
playerViewController.player = player // Your current player instance
playerViewController.transitioningDelegate = self // Custom animation
        
self.present(playerViewController, animated: true, completion: nil)
extension ViewController: UIViewControllerTransitioningDelegate {
  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return PlayerAnimationController(playerLayer: playerLayer) // Your current player's layer
  }
}

PlayerAnimationController.swift PlayerAnimationController.swift

class PlayerAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    
    let playerLayer: AVPlayerLayer
    
    init(playerLayer: AVPlayerLayer) {
        self.playerLayer = playerLayer
    }
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.5
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let toView = transitionContext.view(forKey: .to) else { return }
        
        let containerView = transitionContext.containerView
        containerView.addSubview(toView)
        
        let originalSuperlayer = playerLayer.superlayer
        let originalFrame = playerLayer.frame
        
        let frame = playerLayer.convert(playerLayer.bounds, to: nil)
        containerView.layer.addSublayer(self.playerLayer)
        
        // Start frame
        CATransaction.begin()
        CATransaction.setAnimationDuration(0)
        CATransaction.setDisableActions(true)
        
        self.playerLayer.frame = frame
        
        CATransaction.commit()
        
        toView.alpha = 0
        
        DispatchQueue.main.async {
            let duration = self.transitionDuration(using: transitionContext)
            UIView.animateKeyframes(withDuration: duration, delay: 0) {
                UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1/2) {
                    self.playerLayer.frame = containerView.bounds
                }
                
                UIView.addKeyframe(withRelativeStartTime: 1/2, relativeDuration: 1/2) {
                    toView.alpha = 1.0
                }
            }
            completion: { _ in
                originalSuperlayer?.addSublayer(self.playerLayer)
                self.playerLayer.frame = originalFrame
                
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            }
        }
    }   
}

The sample uses AVPlayerViewController but you can use your own one of course.该示例使用AVPlayerViewController但您当然可以使用自己的一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM