2017-06-19 107 views
0

我有一個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 




    }) 





} 

回答

1

當你設置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