动画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
,那么最好的办法是创建一个使用AVPlayerLayer
为UIView
子它的层,像这样:
class PlayerView: UIView {
override class var layerClass: AnyClass { return AVPlayerLayer.self }
private(set) lazy var playerLayer: AVPlayerLayer = { self.layer as! AVPlayerLayer }()
}
然后你可以使用一个PlayerView
而不是裸AVPlayerLayer
和使用UIKit的动画。由于无法初始化直接AVPlayerLayer
(UIView
使用默认的初始创建它的层),你需要设置PlayerView
的球员是这样的:
playerView?.playerLayer = player
我可以用你的第二个建议,与AVPlayer一起使用UIView,但是,UIView和PlayerLayer仍然不会一致动画。每当我尝试强制动画时,playerLayer都会正确地遮挡UIView,但这是一个尴尬的跳跃,而不是一个流畅的动画。还有什么建议? – Stefan
我需要查看您的修改代码,并更好地描述您不喜欢的事情。 –
它的作用有点只是,playerLayer不会与v和playerView一起动画......另外两个动画完美地协调一致。目前的行为就好像“self.playerLayer?.frame =(self.playerView2?.frame)!”这一行在另外两个开始动画之后读取了一两帧,因此它跳转到帧而不是平滑地为动画制作动画。忘记提及 – Stefan