动画CALayer

问题描述:

我有一个CALayer顶部的UIView。动画CALayer

UIView的动画正是我怎么想,但是这是在它之上的PlayerView似乎“重生”屏幕外,然后动画的立场,即UIView的在开始,然后将动画的UIViews框架。

我想知道是否有CALayers的任何属性可以自动处理这个问题,但我还没有找到任何东西。

下面是这个代码:

let window = UIApplication.shared.keyWindow! 
    v = UIView(frame: CGRect(x: window.frame.origin.x, y: window.frame.origin.y, width: window.frame.width, height: window.frame.height)) 
    let v2 = UIView(frame: .zero) 
    window.addSubview(v!); 
    window.addSubview(v2) 
    v?.backgroundColor = UIColor.black 
    v2.backgroundColor = UIColor.clear 

    v?.layer.cornerRadius = (v?.frame.width)! * 0.025 






    guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else { 
     debugPrint("video.m4v not found") 
     return 
    } 

    player = AVPlayer(url: URL(fileURLWithPath: path)) 

    playerLayer = AVPlayerLayer(player: player) 
    //  playerLayer.frame = playerView.frame 

    playerLayer?.frame = (playerView?.bounds)! 
    playerLayer?.masksToBounds = true 

    playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill 


    v?.layer.addSublayer(playerLayer!) 

    player?.play() 
    player?.isMuted = true 

    //looper 
    NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil) 
    { notification in 
     let t1 = CMTimeMake(5, 100) 
     self.player?.seek(to: t1) 

     self.player?.play() 
    } 







    let superview = playerView?.superview 

    v2.frame = (v2.convert((playerView?.frame)!, from: superview)) 
      v?.frame = (v?.convert((playerView?.frame)!, from: superview))! 

    window.addConstraintsWithFormat("H:|[v0]|", views: v!) 
    window.addConstraintsWithFormat("V:|[v0]|", views: v!) 

      playerLayer?.frame = (v?.frame)! 



       self.playerLayer?.frame = (self.v?.frame)! 


    UIView.animate(withDuration: 4, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { 



     self.window?.layoutIfNeeded() 

    }, completion: { (completed) in 


     self.playerLayer?.frame = (self.v?.frame)! 



    }) 


} 

有什么建议?

编辑:

我已经包含了更新后的代码

let window = UIApplication.shared.keyWindow! 
    v = UIView(frame: CGRect(x: window.frame.origin.x, y: window.frame.origin.y, width: window.frame.width, height: window.frame.height)) 
    let v2 = UIView(frame: .zero) 
    window.addSubview(v!); 

    v?.addSubview(playerView2!) 

    window.addSubview(v2) 
    v?.backgroundColor = UIColor.black 
    v2.backgroundColor = UIColor.clear 

    v?.layer.cornerRadius = (v?.frame.width)! * 0.025 










    playerView2?.layer.cornerRadius = (playerView2?.bounds.width)! * 0.025 

    guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else { 
     debugPrint("video.m4v not found") 
     return 
    } 

    player = AVPlayer(url: URL(fileURLWithPath: path)) 

    playerLayer = AVPlayerLayer(player: player) 
    //  playerLayer.frame = playerView.frame 

    playerLayer?.frame = (playerView2?.bounds)! 
    playerLayer?.masksToBounds = true 
    playerLayer?.cornerRadius = (playerView2?.bounds.width)! * 0.025 

    playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill 


    self.playerView2?.layer.addSublayer(playerLayer!) 

//  player?.play() 
    player?.isMuted = true 

    //looper 
    NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil) 
    { notification in 
     let t1 = CMTimeMake(5, 100) 
     self.player?.seek(to: t1) 

//   self.player?.play() 
    } 










    self.playerView2?.frame = (self.v?.bounds)! 
    self.playerLayer?.frame = (self.playerView?.bounds)! 





    UIView.animate(withDuration: 5, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { 



     self.v?.frame = window.frame 

     self.playerView2?.frame = (self.v?.frame)! 

     self.playerLayer?.frame = (self.playerView2?.frame)! 



     self.window?.layoutIfNeeded() 

    }, completion: { (completed) in 




    }) 





} 

当你设置playerLayer.frame你得到一个隐含的动画。

如果你不希望任何动画,暂时禁用隐式动画这样的:

 UIView.animate(withDuration: 4, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { 
      self.window?.layoutIfNeeded() 
     }, completion: { (completed) in 
      let priorValue = CATransaction.disableActions() 
      CATransaction.setDisableActions(true) 
      self.playerLayer?.frame = self.v!.frame 
      CATransaction.setDisableActions(priorValue) 
     }) 

如果你想动画playerLayer.frame,那么最好的办法是创建一个使用AVPlayerLayerUIView子它的层,像这样:

class PlayerView: UIView { 
    override class var layerClass: AnyClass { return AVPlayerLayer.self } 
    private(set) lazy var playerLayer: AVPlayerLayer = { self.layer as! AVPlayerLayer }() 
} 

然后你可以使用一个PlayerView而不是裸AVPlayerLayer和使用UIKit的动画。由于无法初始化直接AVPlayerLayerUIView使用默认的初始创建它的层),你需要设置PlayerView的球员是这样的:

 playerView?.playerLayer = player 
+0

我可以用你的第二个建议,与AVPlayer一起使用UIView,但是,UIView和PlayerLayer仍然不会一致动画。每当我尝试强制动画时,playerLayer都会正确地遮挡UIView,但这是一个尴尬的跳跃,而不是一个流畅的动画。还有什么建议? – Stefan

+0

我需要查看您的修改代码,并更好地描述您不喜欢的事情。 –

+0

它的作用有点只是,playerLayer不会与v和playerView一起动画......另外两个动画完美地协调一致。目前的行为就好像“self.playerLayer?.frame =(self.playerView2?.frame)!”这一行在另外两个开始动画之后读取了一两帧,因此它跳转到帧而不是平滑地为动画制作动画。忘记提及 – Stefan