使用UIPropertyAnimator动画AVPlayerLayer

时间:2017-10-05 14:01:40

标签: ios swift animation uiview calayer

我正在尝试为UIView中的子图层设置动画。子层是AVPlayerLayer。虽然在正常生活中很容易为CALayer制作动画,但是当UIPropertyAnimator驱动动画时,我很难做到这一点。我真的想使用UIPropertyAnimator,因为使用关键帧交互式动画非常简单。

这是一个演示该问题的游乐场。我希望绿色CALAyer能够跟随它的父母蓝色UIView。但它恰好在动画的结束框架上,再也不会再移动了。

import UIKit
import AVKit

class BlueSubview: UIView {
let subLayer: AVPlayerLayer

init() {
    let player = AVPlayer(url: URL(string: "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8")! )
    subLayer = AVPlayerLayer(player: player)
    super.init(frame: .zero)

    layer.addSublayer(subLayer)
    backgroundColor = .blue
    player.play()
}

required init?(coder aDecoder: NSCoder) {
    fatalError()
    super.init(coder: aDecoder)
}

override func layoutSubviews() {
    super.layoutSubviews()
    CATransaction.begin()
    CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
    subLayer.frame = bounds
    CATransaction.commit()
}
}

class BlurDemoViewController: UIViewController {
let subview = BlueSubview()
var animator: UIViewPropertyAnimator?

override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(subview)
    subview.translatesAutoresizingMaskIntoConstraints = false
    subview.frame = view.bounds
    subview.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    // animator does all the hard work and just lets us tell it what fraction of its animation we want to see. note that duration is not important here as we will just drive the animation manually
    animator = UIViewPropertyAnimator(duration: 10, curve: .linear) {
        self.subview.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
    }

    // make a slider always at the bottom of view
    let slider = UISlider()
    slider.frame.origin.x = 20
    slider.frame.origin.y = view.frame.size.height - slider.frame.size.height - 20
    slider.frame.size.width = view.frame.size.width - 40
    slider.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
    slider.value = 1
    slider.addTarget(self, action: #selector(sliderValueChanged), for: .valueChanged)
    view.addSubview(slider)
}

// this function will be called by UISlider when its value changes. It needs @objc so that it has a #selector (which UISlider uses to send target-action events)
@objc private func sliderValueChanged(sender: UISlider) {
    // The green layer doesn't follow it's blue superview with the animator
    animator?.fractionComplete = CGFloat(1 - sender.value)


    // This works if I don't use the animator
    // subview.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(sender.value) * view.bounds.width, height: CGFloat(sender.value) * view.bounds.height)
}
}

// now just instantiate a blur demo vc and give it an image to show
let vc = BlurDemoViewController()
// PlaygroundSupport allows us to show a live view (controller)
import PlaygroundSupport
PlaygroundPage.current.liveView = vc

谢谢!

0 个答案:

没有答案