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

use*_*512 12 ios avplayer swift swift4

tl;dr 我试图在 Twitter 应用程序中重新创建这个:https : //i.imgur.com/173CVyM.mp4

如您所见,Twitter 在提要(表格视图单元格)中播放视频,当视频被点击时,视频会平滑地过渡到它自己的视图控制器,而不会停止或缓冲视频。

我已经完成了在提要部分中播放的视频(在表格视图单元格中),但现在我被困在如何实际将视频平滑地转换为点击的视图控制器上。

在高层次上,我需要在这里做什么?

我当前的设置有一个AVPlayer实例作为每个表视图单元格的一部分。我会将AVPlayer实例传递给视图控制器并从那里继续播放视频吗?内存管理呢?我觉得AVPlayer每个表格视图单元格都有一个实例会导致一些问题,但我不完全确定。

作为第二个问题,如果我想忽略花哨的动画/过渡,当在表格视图单元格中点击视频时,我如何继续在视图控制器中无缝播放视频?

iUr*_*rii 3

要从视频单元转换到播放器控制器,您可以使用AVPlayerLayer自定义动画,例如:

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)
Run Code Online (Sandbox Code Playgroud)
extension ViewController: UIViewControllerTransitioningDelegate {
  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return PlayerAnimationController(playerLayer: playerLayer) // Your current player's layer
  }
}
Run Code Online (Sandbox Code Playgroud)

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)
            }
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)

该示例使用AVPlayerViewController但您当然可以使用您自己的。