이번 포스트에선 UIViewPropertyAnimator에 대해 알아 보도록 하겠습니다.
지난 포스트에서 알아봤듯이 UIView.animate는 Deprecated될 가능성이 높습니다. 따라서 프로젝트 타켓이 10이상인 프로젝트에서 애니메이션을 적용할때 UIViewPropertyAnimator를 사용하는걸 권장합니다.
특징
- iOS 10 부터 사용가능
- UIIView.animate를 대체하는 API
- 애니메이션 상태(시작, 중지, 일시정지 등)를 제어할 수 있다.
- Interactive Animation
Animation State
https://developer.apple.com/documentation/uikit/uiviewanimating
- 애니메이션을 생성하면 Inactive상태가 된다. (초기상태)
- 애니메이션을 Start, Pause하면 Active상태가 된다.
- Active상태에서 Finish하게 되면 Inactive상태로 된다.
- Active상태에서 Stop을 하게되면 Stopped상태가 되는데, 여기서는 애니메이션이 완전히 Finish된 상태가 아니다.
UIViewPropertyAnimator클래스를 이용하며, runningPropertyAnimator메서드를 이용하거나
UIViewPropertyAnimator 생성자를 이용해서 애니메이션을 적용합니다.
- animator 생성
runningPropertyAnimator
var animator: UIViewPropertyAnimator?
@IBAction func start(_ sender: Any) {
animator = UIViewPropertyAnimator.runningPropertyAnimator(
withDuration: 3.0, delay: 0, options: [],
animations: {
self.animate()
}, completion: { position in
switch position {
case .current:
print("current")
case .start:
print("start")
case .end:
print("end")
}
})
}
UIViewPropertyAnimator 생성자
@IBAction func start(_ sender: Any) {
// curve 파라미터에는 easeInOut, easeIn, easeOut, linear 옵션을 사용할 수 있다.
animator = UIViewPropertyAnimator(duration: 3.0, curve: .linear) {
self.animate()
}
// completion handler가 따로 없어서 필요하면 추가할 수 있다.
animator?.addCompletion({ position in
switch position {
case .current:
print("current")
case .start:
print("start")
case .end:
print("end")
}
})
// 생성자로 애니메이션을 추가하면 꼭 startAnimation을 호출해야 애니메이션이 시작된다.
animator?.startAnimation()
}
UIView.animate와 같은 파라미터를 갖지만 completion의 타입이 UIView.animate때와 다릅니다.
UIView.animate의 completion은 애니메이션의 성공여부인 Boolean의 타입이였다면,
UIViewPropertyAnimator의 completion타입은 종료된 위치의 상태값을 타나내는 열거형(current, start, end)이 전달됩니다.
- animator 중지
@IBAction func pause(_ sender: Any) {
animator?.pauseAnimation()
}
- animator (재)시작
@IBAction func resume(_ sender: Any) {
animator?.startAnimation()
}
- animator 정지
- true를 전달하면 별도의 마무리 없이 정지되며, Inactive상태로 돌아간다.
- false를 전달하면 완전이 애니메이션이 제거되지 않는 Stopped상태가 되기 때문에 보통 finishAnimation과 함께 사용된다.
- finishAnimation이 호출되면 completion handler가 호출되고, Inactive상태로 전환되게 됩니다.
// true
animator.stopAnimation(true)
// false
animator.stopAnimation(false)
animator.finishAnimation(at: .current)
//---------------------------------------------//
@IBAction func stop(_ sender: Any) {
animator?.stopAnimation(false)
animator?.finishAnimation(at: .current)
}
- animator 추가
Stopped상태에서 추가하게되면 Crash가 발생한다.
반드시 Inactive, Active상태에서 애니메이션을 추가해야됩니다.
Active 상태에선 애니메이션이 추가되면 애니메이션중에 남은 시간동안 추가되고,
Inactive 상태에서 추가되면 처음부터 애니메이션이 추가된 상태로 애니메이션이 진행된다.
@IBAction func add(_ sender: Any) {
animator?.addAnimations({
self.objectView.backgroundColor = .blue
self.objectView.frame = CGRect(x: 200, y: 200, width: 50, height: 50)
}, delayFactor: 0)
}
- Interactive Animation
UIViewPropertyAnimator는 fractionComplete를 통해 interactive 애니메이션 지원이 쉽게 가능합니다!
fractionComplete는 0과 1사이의 값을 가지며, 들어온 값에 의해 애니메이션이 자유롭게 바뀔수가 있다.
//Slider와 연결되있다고 가정할때
animator?.fractionComplete = CGFloat(sender.value)
전체 예제)
import UIKit
class PropertyAnimatorViewController: UIViewController {
@IBOutlet weak var objectView: UIView!
var animator: UIViewPropertyAnimator?
func animate() {
let targetFrame = CGRect(x: view.center.x - 150, y: view.center.y - 150, width: 300, height: 300)
objectView.frame = targetFrame
}
@IBAction func start(_ sender: Any) {
animator = UIViewPropertyAnimator.runningPropertyAnimator(
withDuration: 3.0, delay: 0, options: [],
animations: {
self.animate()
}, completion: { position in
switch position {
case .current:
print("current")
case .start:
print("start")
case .end:
print("end")
}
})
}
@IBAction func pause(_ sender: Any) {
animator?.pauseAnimation()
}
@IBAction func stop(_ sender: Any) {
animator?.stopAnimation(false)
animator?.finishAnimation(at: .current)
}
@IBAction func resume(_ sender: Any) {
animator?.startAnimation()
}
@IBAction func add(_ sender: Any) {
animator?.addAnimations({
self.objectView.backgroundColor = .blue
self.objectView.frame = CGRect(x: 200, y: 200, width: 50, height: 50)
}, delayFactor: 0)
}
@IBAction func sliderChange(_ sender: UISlider) {
animator?.fractionComplete = CGFloat(sender.value)
}
}
참조 : https://developer.apple.com/documentation/uikit/uiviewpropertyanimator
'iOS' 카테고리의 다른 글
[iOS] 애플 로그인 사용해보기(Sign in with Apple) (0) | 2020.03.04 |
---|---|
[iOS] Autolayout으로 제약조건을 걸었을때 Animation 방법 (0) | 2019.12.23 |
[iOS] Animation 방법(UIView.animateKeyframes) (0) | 2019.12.23 |
[iOS] Animation 방법(UIView.animate) (2) | 2019.12.23 |
[iOS] 개발자 계정 및 인증서 가이드 (0) | 2019.10.31 |